viced: avoid aborting on host table exhaustion
[openafs.git] / src / viced / host.c
index 868d272..0630067 100644 (file)
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
+#include <roken.h>
 
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#include <winsock2.h>
-#else
+#ifdef HAVE_SYS_FILE_H
 #include <sys/file.h>
-#include <netdb.h>
-#include <netinet/in.h>
 #endif
 
-#include <afs/stds.h>
 #include <rx/xdr.h>
-#include <afs/assert.h>
+#include <afs/afs_assert.h>
 #include <lwp.h>
 #include <lock.h>
 #include <afs/afsint.h>
@@ -51,7 +44,6 @@
 #include <afs/com_err.h>
 #include <rx/rx.h>
 #include <afs/cellconfig.h>
-#include <stdlib.h>
 #include "viced_prototypes.h"
 #include "viced.h"
 #include "host.h"
@@ -208,7 +200,7 @@ GetHTBlock(void)
 
     if (HTBlocks == h_MAXHOSTTABLES) {
        ViceLog(0, ("h_MAXHOSTTABLES reached\n"));
-       ShutDownAndCore(PANIC);
+       return;
     }
 
     block = (struct HTBlock *)malloc(sizeof(struct HTBlock));
@@ -218,7 +210,7 @@ GetHTBlock(void)
     }
 #ifdef AFS_PTHREAD_ENV
     for (i = 0; i < (h_HTSPERBLOCK); i++)
-       assert(pthread_cond_init(&block->entry[i].cond, NULL) == 0);
+       CV_INIT(&block->entry[i].cond, "block entry", CV_DEFAULT, 0);
 #endif /* AFS_PTHREAD_ENV */
     for (i = 0; i < (h_HTSPERBLOCK); i++)
        Lock_Init(&block->entry[i].lock);
@@ -241,7 +233,8 @@ GetHT(void)
 
     if (HTFree == NULL)
        GetHTBlock();
-    assert(HTFree != NULL);
+    if (HTFree == NULL)
+       return NULL;
     entry = HTFree;
     HTFree = entry->next;
     HTs++;
@@ -304,19 +297,17 @@ hpr_Initialize(struct ubik_client **uclient)
     /* Most callers use secLevel==1, however, the fileserver uses secLevel==2
      * to force use of the KeyFile.  secLevel == 0 implies -noauth was
      * specified. */
-    if ((afsconf_GetLatestKey(tdir, 0, 0) == 0)) {
-        code = afsconf_ClientAuthSecure(tdir, &sc, &scIndex);
-        if (code)
-           ViceLog(0, ("hpr_Initialize: clientauthsecure returns %d %s (so trying noauth)", code, afs_error_message(code)));
-        if (code)
-            scIndex = RX_SECIDX_NULL;
-    } else {
-       afsconf_ClientAuthToken(&info, 0, &sc, &scIndex, NULL);
+    code = afsconf_ClientAuthSecure(tdir, &sc, &scIndex);
+    if (code) {
+       ViceLog(0, ("hpr_Initialize: clientauthsecure returns %d %s "
+                   "(so trying noauth)", code, afs_error_message(code)));
+       scIndex = RX_SECIDX_NULL;
+       sc = rxnull_NewClientSecurityObject();
     }
-    if ((scIndex == RX_SECIDX_NULL) && (sc == NULL))
-        sc = rxnull_NewClientSecurityObject();
+
     if (scIndex == RX_SECIDX_NULL)
-       ViceLog(0, ("hpr_Initialize: Could not get afs tokens, running unauthenticated. [%d]", code));
+       ViceLog(0, ("hpr_Initialize: Could not get afs tokens, "
+                   "running unauthenticated. [%d]", code));
 
     memset(serverconns, 0, sizeof(serverconns));        /* terminate list!!! */
     for (i = 0; i < info.numServers; i++) {
@@ -358,7 +349,7 @@ hpr_GetHostCPS(afs_int32 host, prlist *CPS)
     if (!uclient) {
         code = hpr_Initialize(&uclient);
        if (!code)
-           assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
        else
            return code;
     }
@@ -392,7 +383,7 @@ hpr_NameToId(namelist *names, idlist *ids)
     if (!uclient) {
         code = hpr_Initialize(&uclient);
        if (!code)
-           assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
        else
            return code;
     }
@@ -417,7 +408,7 @@ hpr_IdToName(idlist *ids, namelist *names)
     if (!uclient) {
         code = hpr_Initialize(&uclient);
        if (!code)
-           assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
        else
            return code;
     }
@@ -441,7 +432,7 @@ hpr_GetCPS(afs_int32 id, prlist *CPS)
     if (!uclient) {
         code = hpr_Initialize(&uclient);
        if (!code)
-           assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
        else
            return code;
     }
@@ -592,7 +583,7 @@ h_gethostcps_r(struct host *host, afs_int32 now)
        slept = 1;              /* I did sleep */
        host->hostFlags |= HCPS_WAITING;        /* I am sleeping now */
 #ifdef AFS_PTHREAD_ENV
-       pthread_cond_wait(&host->cond, &host_glock_mutex);
+       CV_WAIT(&host->cond, &host_glock_mutex);
 #else /* AFS_PTHREAD_ENV */
        if ((code = LWP_WaitProcess(&(host->hostFlags))) != LWP_SUCCESS)
            ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
@@ -653,7 +644,7 @@ h_gethostcps_r(struct host *host, afs_int32 now)
     if (host->hostFlags & HCPS_WAITING) {      /* somebody is waiting */
        host->hostFlags &= ~HCPS_WAITING;
 #ifdef AFS_PTHREAD_ENV
-       assert(pthread_cond_broadcast(&host->cond) == 0);
+       CV_BROADCAST(&host->cond);
 #else /* AFS_PTHREAD_ENV */
        if ((code = LWP_NoYieldSignal(&(host->hostFlags))) != LWP_SUCCESS)
            ViceLog(0, ("LWP_NoYieldSignal returns %d\n", code));
@@ -684,17 +675,18 @@ h_flushhostcps(afs_uint32 hostaddr, afs_uint16 hport)
  */
 #define        DEF_ROPCONS 2115
 
-struct host *
+static struct host *
 h_Alloc_r(struct rx_connection *r_con)
 {
     struct servent *serverentry;
     struct host *host;
-    afs_int32 now;
 #if FS_STATS_DETAILED
     afs_uint32 newHostAddr_HBO;        /*New host IP addr, in host byte order */
 #endif /* FS_STATS_DETAILED */
 
     host = GetHT();
+    if (!host)
+       return NULL;
 
     host->host = rxr_HostOf(r_con);
     host->port = rxr_PortOf(r_con);
@@ -717,7 +709,7 @@ h_Alloc_r(struct rx_connection *r_con)
     /* Make a callback channel even for the console, on the off chance that it
      * makes a request that causes a break call back.  It shouldn't. */
     h_SetupCallbackConn_r(host);
-    now = host->LastCall = host->cpsCall = host->ActiveCall = FT_ApproxTime();
+    host->LastCall = host->cpsCall = host->ActiveCall = FT_ApproxTime();
     host->hostFlags = 0;
     host->hcps.prlist_val = NULL;
     host->hcps.prlist_len = 0;
@@ -756,6 +748,7 @@ h_SetupCallbackConn_r(struct host * host)
        rx_NewConnection(host->host, host->port, 1, sc, 0);
     rx_SetConnDeadTime(host->callback_rxcon, 50);
     rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
+    rx_SetConnSecondsUntilNatPing(host->callback_rxcon, 20);
 }
 
 /* h_Lookup_r
@@ -776,7 +769,7 @@ h_Lookup_r(afs_uint32 haddr, afs_uint16 hport, struct host **hostp)
   restart:
     for (chain = hostAddrHashTable[index]; chain; chain = chain->next) {
        host = chain->hostPtr;
-       assert(host);
+       osi_Assert(host);
        if (!(host->hostFlags & HOSTDELETED) && chain->addr == haddr
            && chain->port == hport) {
            if ((host->hostFlags & HWHO_INPROGRESS) &&
@@ -823,7 +816,7 @@ h_LookupUuid_r(afsUUID * uuidp)
 
     for (chain = hostUuidHashTable[index]; chain; chain = chain->next) {
        host = chain->hostPtr;
-       assert(host);
+       osi_Assert(host);
        if (!(host->hostFlags & HOSTDELETED) && host->interface
            && afs_uuid_equal(&host->interface->uuid, uuidp)) {
             return host;
@@ -963,23 +956,18 @@ h_TossStuff_r(struct host *host)
 
 
 
-/* h_Enumerate: Calls (*proc)(host, held, param) for at least each host in the
+/* h_Enumerate: Calls (*proc)(host, param) for at least each host in the
  * system at the start of the enumeration (perhaps more).  Hosts may be deleted
  * (have delete flag set); ditto for clients.  refCount is always incremented
- * before (*proc) is called.  The param flags is passed to (*proc) as the
- * param flags, permitting (*proc) to stop the enumeration (BAIL).
- *
- * Needed?  Why not always h_Hold_r and h_Release_r in (*proc), or even -never-
- * h_Hold_r or h_Release_r in (*proc)?
+ * before (*proc) is called.
  *
- * **The proc should return 0 if the host should be released, 1 if it should
- * be held after enumeration.
+ * The return value of the proc is a set of flags. The proc should set
+ * H_ENUMERATE_BAIL(foo) if the enumeration of hosts should be stopped early.
  */
 void
-h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
+h_Enumerate(int (*proc) (struct host*, void *), void *param)
 {
     struct host *host, **list;
-    int *flags;
     int i, count;
     int totalCount;
 
@@ -990,13 +978,7 @@ h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
     }
     list = (struct host **)malloc(hostCount * sizeof(struct host *));
     if (!list) {
-       ViceLog(0, ("Failed malloc in h_Enumerate (list)\n"));
-       assert(0);
-    }
-    flags = (int *)malloc(hostCount * sizeof(int));
-    if (!flags) {
-       ViceLog(0, ("Failed malloc in h_Enumerate (flags)\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in h_Enumerate (list)\n"));
     }
     for (totalCount = count = 0, host = hostList;
          host && totalCount < hostCount;
@@ -1016,41 +998,51 @@ h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
     }
     H_UNLOCK;
     for (i = 0; i < count; i++) {
-       flags[i] = (*proc) (list[i], flags[i], param);
+       int flags;
+       flags = (*proc) (list[i], param);
+       H_LOCK;
        h_Release_r(list[i]);
+       H_UNLOCK;
        /* bail out of the enumeration early */
-       if (H_ENUMERATE_ISSET_BAIL(flags[i]))
+       if (H_ENUMERATE_ISSET_BAIL(flags)) {
            break;
+       } else if (flags) {
+           ViceLog(0, ("h_Enumerate got back invalid return value %d\n", flags));
+           ShutDownAndCore(PANIC);
+       }
+    }
+    if (i < count-1) {
+       /* we bailed out of enumerating hosts early; we still have holds on
+        * some of the hosts in 'list', so release them */
+       i++;
+       H_LOCK;
+       for ( ; i < count; i++) {
+           h_Release_r(list[i]);
+       }
+       H_UNLOCK;
     }
     free((void *)list);
-    free((void *)flags);
 }      /* h_Enumerate */
 
 
 /* h_Enumerate_r (revised):
- * Calls (*proc)(host, flags, param) for each host in hostList, starting
+ * Calls (*proc)(host, param) for each host in hostList, starting
  * at enumstart. Called only under H_LOCK.  Hosts may be deleted (have
  * delete flag set); ditto for clients.  refCount is always incremented
- * before (*proc) is called.  The param flags is passed to (*proc) as the
- * param flags, permitting (*proc) to stop the enumeration (BAIL).
- *
- * Needed?  Why not always h_Hold_r and h_Release_r in (*proc), or even -never-
- * h_Hold_r or h_Release_r in (*proc)?
+ * before (*proc) is called.
  *
  * @note Assumes that hostList is only prepended to, that a host is never
  *       inserted into the middle. Otherwise this would not be guaranteed to
  *       terminate.
  *
- * **The proc should return 0 if the host should be released, 1 if it should
- * be held after enumeration.
+ * The return value of the proc is a set of flags. The proc should set
+ * H_ENUMERATE_BAIL(foo) if the enumeration of hosts should be stopped early.
  */
 void
-h_Enumerate_r(int (*proc) (struct host *, int, void *),
+h_Enumerate_r(int (*proc) (struct host *, void *),
              struct host *enumstart, void *param)
 {
     struct host *host, *next;
-    int flags = 0;
-    int nflags = 0;
     int count;
     int origHostCount;
 
@@ -1089,7 +1081,7 @@ h_Enumerate_r(int (*proc) (struct host *, int, void *),
      * h_Release_r */
     origHostCount = hostCount;
 
-    for (count = 0, host = enumstart; host && count < origHostCount; host = next, flags = nflags, count++) {
+    for (count = 0, host = enumstart; host && count < origHostCount; host = next, count++) {
        next = host->next;
 
        /* find the next non-deleted host */
@@ -1101,14 +1093,21 @@ h_Enumerate_r(int (*proc) (struct host *, int, void *),
                ShutDownAndCore(PANIC);
            }
        }
-       if (next && !H_ENUMERATE_ISSET_BAIL(flags))
+       if (next)
            h_Hold_r(next);
 
        if (!(host->hostFlags & HOSTDELETED)) {
-           flags = (*proc) (host, flags, param);
+           int flags;
+           flags = (*proc) (host, param);
            if (H_ENUMERATE_ISSET_BAIL(flags)) {
                h_Release_r(host); /* this might free up the host */
+               if (next) {
+                   h_Release_r(next);
+               }
                break;
+           } else if (flags) {
+               ViceLog(0, ("h_Enumerate_r got back invalid return value %d\n", flags));
+               ShutDownAndCore(PANIC);
            }
        }
        h_Release_r(host); /* this might free up the host */
@@ -1155,8 +1154,7 @@ h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host)
     /* insert into beginning of list for this bucket */
     chain = (struct h_UuidHashChain *)malloc(sizeof(struct h_UuidHashChain));
     if (!chain) {
-       ViceLog(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n"));
     }
     chain->hostPtr = host;
     chain->next = hostUuidHashTable[index];
@@ -1188,7 +1186,7 @@ h_DeleteHostFromUuidHashTable_r(struct host *host)
      if (LogLevel >= 125)
         afsUUID_to_string(&host->interface->uuid, uuid1, 127);
      for (uhp = &hostUuidHashTable[index]; (uth = *uhp); uhp = &uth->next) {
-         assert(uth->hostPtr);
+         osi_Assert(uth->hostPtr);
         if (uth->hostPtr == host) {
             ViceLog(125,
                     ("h_DeleteHostFromUuidHashTable_r: host %" AFS_PTR_FMT " (uuid %s %s:%d)\n",
@@ -1219,8 +1217,8 @@ invalidateInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
     struct Interface *interface;
     char hoststr[16], hoststr2[16];
 
-    assert(host);
-    assert(host->interface);
+    osi_Assert(host);
+    osi_Assert(host->interface);
 
     ViceLog(125, ("invalidateInterfaceAddr : host %" AFS_PTR_FMT " (%s:%d) addr %s:%d\n",
                  host, afs_inet_ntoa_r(host->host, hoststr),
@@ -1317,12 +1315,7 @@ removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port)
                     rxconn = NULL;
                 }
 
-                if (!sc)
-                    sc = rxnull_NewClientSecurityObject();
-                host->callback_rxcon =
-                    rx_NewConnection(host->host, host->port, 1, sc, 0);
-                rx_SetConnDeadTime(host->callback_rxcon, 50);
-                rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
+               h_SetupCallbackConn_r(host);
             }
         } else {
             /* not the primary addr/port, just invalidate it */
@@ -1342,8 +1335,7 @@ createHostAddrHashChain_r(int index, afs_uint32 addr, afs_uint16 port, struct ho
     /* insert into beginning of list for this bucket */
     chain = (struct h_AddrHashChain *)malloc(sizeof(struct h_AddrHashChain));
     if (!chain) {
-       ViceLog(0, ("Failed malloc in h_AddHostToAddrHashTable_r\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in h_AddHostToAddrHashTable_r\n"));
     }
     chain->hostPtr = host;
     chain->next = hostAddrHashTable[index];
@@ -1379,7 +1371,7 @@ reconcileHosts_r(afs_uint32 addr, afs_uint16 port, struct host *newHost,
             AFS_PTR_FMT, afs_inet_ntoa_r(addr, hoststr), ntohs(port),
             newHost, oldHost));
 
-    assert(oldHost != newHost);
+    osi_Assert(oldHost != newHost);
     caps.Capabilities_val = NULL;
 
     if (!sc) {
@@ -1529,8 +1521,8 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
     struct Interface *interface;
     char hoststr[16], hoststr2[16];
 
-    assert(host);
-    assert(host->interface);
+    osi_Assert(host);
+    osi_Assert(host->interface);
 
     /*
      * Make sure this address is on the list of known addresses
@@ -1563,8 +1555,7 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
     interface = (struct Interface *)
        malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * number));
     if (!interface) {
-       ViceLog(0, ("Failed malloc in addInterfaceAddr_r\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in addInterfaceAddr_r\n"));
     }
     interface->numberOfInterfaces = number + 1;
     interface->uuid = host->interface->uuid;
@@ -1596,8 +1587,8 @@ removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
     struct Interface *interface;
     char hoststr[16], hoststr2[16];
 
-    assert(host);
-    assert(host->interface);
+    osi_Assert(host);
+    osi_Assert(host->interface);
 
     ViceLog(125, ("removeInterfaceAddr : host %" AFS_PTR_FMT " (%s:%d) addr %s:%d\n",
                  host, afs_inet_ntoa_r(host->host, hoststr),
@@ -1743,6 +1734,7 @@ h_GetHost_r(struct rx_connection *tcon)
             cb_in = rx_NewConnection(haddr, hport, 1, sc, 0);
             rx_SetConnDeadTime(cb_in, 50);
             rx_SetConnHardDeadTime(cb_in, AFS_HARDDEADTIME);
+           rx_SetConnSecondsUntilNatPing(cb_in, 20);
 
             code =
                 RXAFSCB_TellMeAboutYourself(cb_in, &interf, &caps);
@@ -1756,8 +1748,7 @@ h_GetHost_r(struct rx_connection *tcon)
            ((code == 0) && (afs_uuid_equal(&interf.uuid, &nulluuid)))) {
            identP = (struct Identity *)malloc(sizeof(struct Identity));
            if (!identP) {
-               ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-               assert(0);
+               ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
            }
            identP->valid = 0;
            rx_SetSpecific(tcon, rxcon_ident_key, identP);
@@ -1798,8 +1789,7 @@ h_GetHost_r(struct rx_connection *tcon)
            interfValid = 1;
            identP = (struct Identity *)malloc(sizeof(struct Identity));
            if (!identP) {
-               ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-               assert(0);
+               ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
            }
            identP->valid = 1;
            identP->uuid = interf.uuid;
@@ -1964,6 +1954,8 @@ h_GetHost_r(struct rx_connection *tcon)
        }
     } else {
        host = h_Alloc_r(tcon); /* returned held and locked */
+       if (!host)
+           goto gethost_out;
        h_gethostcps_r(host, FT_ApproxTime());
        if (!(host->Console & 1)) {
            int pident = 0;
@@ -1987,8 +1979,7 @@ h_GetHost_r(struct rx_connection *tcon)
                    pident = 1;
 
                if (!identP) {
-                   ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-                   assert(0);
+                   ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
                }
                identP->valid = 0;
                if (!pident)
@@ -2006,8 +1997,7 @@ h_GetHost_r(struct rx_connection *tcon)
                    pident = 1;
 
                if (!identP) {
-                   ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-                   assert(0);
+                   ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
                }
                identP->valid = 1;
                interfValid = 1;
@@ -2159,7 +2149,7 @@ h_GetHost_r(struct rx_connection *tcon)
                                ("InitCallBackState3 success on host %" AFS_PTR_FMT " (%s:%d)\n",
                                 host, afs_inet_ntoa_r(host->host, hoststr),
                                 ntohs(host->port)));
-                       assert(interfValid == 1);
+                       osi_Assert(interfValid == 1);
                        initInterfaceAddr_r(host, &interf);
                    }
                }
@@ -2233,9 +2223,7 @@ h_InitHostPackage(void)
     }
     rxcon_ident_key = rx_KeyCreate((rx_destructor_t) free);
     rxcon_client_key = rx_KeyCreate((rx_destructor_t) 0);
-#ifdef AFS_PTHREAD_ENV
-    assert(pthread_mutex_init(&host_glock_mutex, NULL) == 0);
-#endif /* AFS_PTHREAD_ENV */
+    MUTEX_INIT(&host_glock_mutex, "host glock", MUTEX_DEFAULT, 0);
 }
 
 static int
@@ -2273,8 +2261,7 @@ MapName_r(char *aname, char *acell, afs_int32 * aval)
            foreign = 1;        /* attempt cross-cell authentication */
            tname = (char *)malloc(PR_MAXNAMELEN);
            if (!tname) {
-               ViceLog(0, ("Failed malloc in MapName_r\n"));
-               assert(0);
+               ViceLogThenPanic(0, ("Failed malloc in MapName_r\n"));
            }
            strcpy(tname, aname);
            tname[anamelen] = '@';
@@ -2377,11 +2364,12 @@ h_FindClient_r(struct rx_connection *tcon)
     client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
     if (client && client->sid == rxr_CidOf(tcon)
        && client->VenusEpoch == rxr_GetEpoch(tcon)
-       && !(client->host->hostFlags & HOSTDELETED)) {
+       && !(client->host->hostFlags & HOSTDELETED)
+       && !client->deleted) {
 
        client->refCount++;
        h_Hold_r(client->host);
-       if (!client->deleted && client->prfail != 2) {
+       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 rx_SetSpecific
@@ -2544,7 +2532,7 @@ h_FindClient_r(struct rx_connection *tcon)
         * possible failure modes that we will disable it again */
        /* Turn off System:Administrator for safety
         * if (AL_IsAMember(SystemId, client->CPS) == 0)
-        * assert(AL_DisableGroup(SystemId, client->CPS) == 0); */
+        * osi_Assert(AL_DisableGroup(SystemId, client->CPS) == 0); */
     }
 
     /* Now, tcon may already be set to a rock, since we blocked with no host
@@ -2578,17 +2566,25 @@ h_FindClient_r(struct rx_connection *tcon)
                created = 0;
            }
            oldClient->refCount++;
+
+           h_Hold_r(oldClient->host);
+           h_Release_r(client->host);
+
            H_UNLOCK;
            ObtainWriteLock(&oldClient->lock);
            H_LOCK;
            client = oldClient;
+           host = oldClient->host;
        } else {
-           ViceLog(0, ("FindClient: deleted client %p(%x) already had "
-                       "conn %p (host %s:%d), stolen by client %p(%x)\n",
-                       oldClient, oldClient->sid, tcon,
-                       afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
-                       ntohs(rxr_PortOf(tcon)),
-                       client, client->sid));
+           ViceLog(0, ("FindClient: deleted client %p(%x ref %d host %p href "
+                       "%d) already had conn %p (host %s:%d, cid %x), stolen "
+                       "by client %p(%x, ref %d host %p href %d)\n",
+                       oldClient, oldClient->sid, oldClient->refCount,
+                       oldClient->host, oldClient->host->refCount, tcon,
+                       afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
+                       ntohs(rxr_PortOf(tcon)), rxr_CidOf(tcon),
+                       client, client->sid, client->refCount,
+                       client->host, client->host->refCount));
            /* rx_SetSpecific will be done immediately below */
        }
     }
@@ -2629,7 +2625,7 @@ h_FindClient_r(struct rx_connection *tcon)
 int
 h_ReleaseClient_r(struct client *client)
 {
-    assert(client->refCount > 0);
+    osi_Assert(client->refCount > 0);
     client->refCount--;
     return 0;
 }
@@ -2674,6 +2670,16 @@ GetClient(struct rx_connection *tcon, struct client **cp)
        H_UNLOCK;
        return VICETOKENDEAD;
     }
+    if (client->deleted) {
+       ViceLog(0, ("GetClient: got deleted client, connection will appear "
+                   "anonymous; tcon %p cid %x client %p ref %d host %p "
+                   "(%s:%d) href %d ViceId %d\n",
+                   tcon, rxr_CidOf(tcon), client, client->refCount,
+                   client->host,
+                   afs_inet_ntoa_r(client->host->host, hoststr),
+                   (int)ntohs(client->host->port), client->host->refCount,
+                   (int)client->ViceId));
+    }
 
     client->refCount++;
     *cp = client;
@@ -2706,8 +2712,7 @@ h_UserName(struct client *client)
     lids.idlist_len = 1;
     lids.idlist_val = (afs_int32 *) malloc(1 * sizeof(afs_int32));
     if (!lids.idlist_val) {
-       ViceLog(0, ("Failed malloc in h_UserName\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in h_UserName\n"));
     }
     lnames.namelist_len = 0;
     lnames.namelist_val = (prname *) 0;
@@ -2735,7 +2740,7 @@ h_PrintStats(void)
 
 
 static int
-h_PrintClient(struct host *host, int flags, void *rock)
+h_PrintClient(struct host *host, void *rock)
 {
     StreamHandle_t *file = (StreamHandle_t *)rock;
     struct client *client;
@@ -2744,41 +2749,40 @@ h_PrintClient(struct host *host, int flags, void *rock)
     char tbuffer[32];
     char hoststr[16];
     time_t LastCall, expTime;
+    struct tm tm;
 
     H_LOCK;
     LastCall = host->LastCall;
     if (host->hostFlags & HOSTDELETED) {
        H_UNLOCK;
-       return flags;
-    }
-    (void)afs_snprintf(tmpStr, sizeof tmpStr,
-                      "Host %s:%d down = %d, LastCall %s",
-                      afs_inet_ntoa_r(host->host, hoststr),
-                      ntohs(host->port), (host->hostFlags & VENUSDOWN),
-                      afs_ctime(&LastCall, tbuffer,
-                                sizeof(tbuffer)));
+       return 0;
+    }
+    strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
+            localtime_r(&LastCall, &tm));
+    snprintf(tmpStr, sizeof tmpStr, "Host %s:%d down = %d, LastCall %s\n",
+            afs_inet_ntoa_r(host->host, hoststr),
+            ntohs(host->port), (host->hostFlags & VENUSDOWN),
+            tbuffer);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
     for (client = host->FirstClient; client; client = client->next) {
        if (!client->deleted) {
-               expTime = client->expTime;
-               (void)afs_snprintf(tmpStr, sizeof tmpStr,
-                                  "    user id=%d,  name=%s, sl=%s till %s",
-                                  client->ViceId, h_UserName(client),
-                                  client->
-                                  authClass ? "Authenticated" :
-                                  "Not authenticated",
-                                  client->
-                                  authClass ? afs_ctime(&expTime, tbuffer,
-                                                        sizeof(tbuffer))
-                                  : "No Limit\n");
-               (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
-           (void)afs_snprintf(tmpStr, sizeof tmpStr, "      CPS-%d is [",
-                              client->CPS.prlist_len);
+           expTime = client->expTime;
+           strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
+                    localtime_r(&expTime, &tm));
+           snprintf(tmpStr, sizeof tmpStr,
+                    "    user id=%d,  name=%s, sl=%s till %s\n",
+                    client->ViceId, h_UserName(client),
+                    client->authClass ? "Authenticated"
+                                      : "Not authenticated",
+                    client->authClass ? tbuffer : "No Limit");
+           (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
+           snprintf(tmpStr, sizeof tmpStr, "      CPS-%d is [",
+                        client->CPS.prlist_len);
            (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
            if (client->CPS.prlist_val) {
-               for (i = 0; i > client->CPS.prlist_len; i++) {
-                   (void)afs_snprintf(tmpStr, sizeof tmpStr, " %d",
-                                      client->CPS.prlist_val[i]);
+               for (i = 0; i < client->CPS.prlist_len; i++) {
+                   snprintf(tmpStr, sizeof tmpStr, " %d",
+                            client->CPS.prlist_val[i]);
                    (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
                }
            }
@@ -2787,7 +2791,7 @@ h_PrintClient(struct host *host, int flags, void *rock)
        }
     }
     H_UNLOCK;
-    return flags;
+    return 0;
 
 }                              /*h_PrintClient */
 
@@ -2803,6 +2807,7 @@ h_PrintClients(void)
     time_t now;
     char tmpStr[256];
     char tbuffer[32];
+    struct tm tm;
 
     StreamHandle_t *file = STREAM_OPEN(AFSDIR_SERVER_CLNTDUMP_FILEPATH, "w");
 
@@ -2813,8 +2818,10 @@ h_PrintClients(void)
        return;
     }
     now = FT_ApproxTime();
-    (void)afs_snprintf(tmpStr, sizeof tmpStr, "List of active users at %s\n",
-                      afs_ctime(&now, tbuffer, sizeof(tbuffer)));
+    strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
+            localtime_r(&now, &tm));
+    snprintf(tmpStr, sizeof tmpStr, "List of active users at %s\n\n",
+            tbuffer);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
     h_Enumerate(h_PrintClient, (char *)file);
     STREAM_REALLYCLOSE(file);
@@ -2825,7 +2832,7 @@ h_PrintClients(void)
 
 
 static int
-h_DumpHost(struct host *host, int flags, void *rock)
+h_DumpHost(struct host *host, void *rock)
 {
     StreamHandle_t *file = (StreamHandle_t *)rock;
 
@@ -2834,19 +2841,20 @@ h_DumpHost(struct host *host, int flags, void *rock)
     char hoststr[16];
 
     H_LOCK;
-    (void)afs_snprintf(tmpStr, sizeof tmpStr,
-                      "ip:%s port:%d hidx:%d cbid:%d lock:%x last:%u active:%u down:%d del:%d cons:%d cldel:%d\n\t hpfailed:%d hcpsCall:%u hcps [",
-                      afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port), host->index,
-                      host->cblist, CheckLock(&host->lock), host->LastCall,
-                      host->ActiveCall, (host->hostFlags & VENUSDOWN),
-                      host->hostFlags & HOSTDELETED, host->Console,
-                      host->hostFlags & CLIENTDELETED, host->hcpsfailed,
-                      host->cpsCall);
+    snprintf(tmpStr, sizeof tmpStr,
+            "ip:%s port:%d hidx:%d cbid:%d lock:%x last:%u active:%u "
+            "down:%d del:%d cons:%d cldel:%d\n\t hpfailed:%d hcpsCall:%u "
+            "hcps [",
+            afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
+            host->index, host->cblist, CheckLock(&host->lock),
+            host->LastCall, host->ActiveCall, (host->hostFlags & VENUSDOWN),
+            host->hostFlags & HOSTDELETED, host->Console,
+            host->hostFlags & CLIENTDELETED, host->hcpsfailed,
+            host->cpsCall);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
     if (host->hcps.prlist_val)
        for (i = 0; i < host->hcps.prlist_len; i++) {
-           (void)afs_snprintf(tmpStr, sizeof tmpStr, " %d",
-                              host->hcps.prlist_val[i]);
+           snprintf(tmpStr, sizeof tmpStr, " %d", host->hcps.prlist_val[i]);
            (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
        }
     sprintf(tmpStr, "] [");
@@ -2863,7 +2871,7 @@ h_DumpHost(struct host *host, int flags, void *rock)
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
 
     H_UNLOCK;
-    return flags;
+    return 0;
 
 }                              /*h_DumpHost */
 
@@ -2875,6 +2883,7 @@ h_DumpHosts(void)
     StreamHandle_t *file = STREAM_OPEN(AFSDIR_SERVER_HOSTDUMP_FILEPATH, "w");
     char tmpStr[256];
     char tbuffer[32];
+    struct tm tm;
 
     if (file == NULL) {
        ViceLog(0,
@@ -2883,8 +2892,9 @@ h_DumpHosts(void)
        return;
     }
     now = FT_ApproxTime();
-    (void)afs_snprintf(tmpStr, sizeof tmpStr, "List of active hosts at %s\n",
-                      afs_ctime(&now, tbuffer, sizeof(tbuffer)));
+    strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
+            localtime_r(&now, &tm));
+    snprintf(tmpStr, sizeof tmpStr, "List of active hosts at %s\n\n", tbuffer);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
     h_Enumerate(h_DumpHost, (char *)file);
     STREAM_REALLYCLOSE(file);
@@ -2900,10 +2910,10 @@ h_DumpHosts(void)
 static int h_stateFillHeader(struct host_state_header * hdr);
 static int h_stateCheckHeader(struct host_state_header * hdr);
 static int h_stateAllocMap(struct fs_dump_state * state);
-static int h_stateSaveHost(struct host * host, int flags, void *rock);
+static int h_stateSaveHost(struct host * host, void *rock);
 static int h_stateRestoreHost(struct fs_dump_state * state);
-static int h_stateRestoreIndex(struct host * h, int flags, void *rock);
-static int h_stateVerifyHost(struct host * h, int flags, void *rock);
+static int h_stateRestoreIndex(struct host * h, void *rock);
+static int h_stateVerifyHost(struct host * h, void *rock);
 static int h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h,
                                  afs_uint32 addr, afs_uint16 port, int valid);
 static int h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h);
@@ -2996,13 +3006,13 @@ h_stateRestoreIndices(struct fs_dump_state * state)
 }
 
 static int
-h_stateRestoreIndex(struct host * h, int flags, void *rock)
+h_stateRestoreIndex(struct host * h, void *rock)
 {
     struct fs_dump_state *state = (struct fs_dump_state *)rock;
     if (cb_OldToNew(state, h->cblist, &h->cblist)) {
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
-    return flags;
+    return 0;
 }
 
 int
@@ -3013,14 +3023,14 @@ h_stateVerify(struct fs_dump_state * state)
 }
 
 static int
-h_stateVerifyHost(struct host * h, int flags, void* rock)
+h_stateVerifyHost(struct host * h, void* rock)
 {
     struct fs_dump_state *state = (struct fs_dump_state *)rock;
     int i;
 
     if (h == NULL) {
        ViceLog(0, ("h_stateVerifyHost: error: NULL host pointer in linked list\n"));
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
 
     if (h->interface) {
@@ -3042,7 +3052,7 @@ h_stateVerifyHost(struct host * h, int flags, void* rock)
        state->bail = 1;
     }
 
-    return flags;
+    return 0;
 }
 
 /**
@@ -3220,7 +3230,7 @@ h_stateAllocMap(struct fs_dump_state * state)
 
 /* function called by h_Enumerate to save a host to disk */
 static int
-h_stateSaveHost(struct host * host, int flags, void* rock)
+h_stateSaveHost(struct host * host, void* rock)
 {
     struct fs_dump_state *state = (struct fs_dump_state *) rock;
     int if_len=0, hcps_len=0;
@@ -3242,7 +3252,7 @@ h_stateSaveHost(struct host * host, int flags, void* rock)
        if_len = sizeof(struct Interface) +
            ((host->interface->numberOfInterfaces-1) * sizeof(struct AddrPort));
        ifp = (struct Interface *) malloc(if_len);
-       assert(ifp != NULL);
+       osi_Assert(ifp != NULL);
        memcpy(ifp, host->interface, if_len);
        hdr.interfaces = host->interface->numberOfInterfaces;
        iov[iovcnt].iov_base = (char *) ifp;
@@ -3253,7 +3263,7 @@ h_stateSaveHost(struct host * host, int flags, void* rock)
        hdr.hcps = host->hcps.prlist_len;
        hcps_len = hdr.hcps * sizeof(afs_int32);
        hcps = (afs_int32 *) malloc(hcps_len);
-       assert(hcps != NULL);
+       osi_Assert(hcps != NULL);
        memcpy(hcps, host->hcps.prlist_val, hcps_len);
        iov[iovcnt].iov_base = (char *) hcps;
        iov[iovcnt].iov_len = hcps_len;
@@ -3286,9 +3296,9 @@ h_stateSaveHost(struct host * host, int flags, void* rock)
     if (hcps)
        free(hcps);
     if (state->bail) {
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
-    return flags;
+    return 0;
 }
 
 /* restores a host from disk */
@@ -3325,7 +3335,7 @@ h_stateRestoreHost(struct fs_dump_state * state)
        ifp_len = sizeof(struct Interface) +
            ((hdr.interfaces-1) * sizeof(struct AddrPort));
        ifp = (struct Interface *) malloc(ifp_len);
-       assert(ifp != NULL);
+       osi_Assert(ifp != NULL);
        iov[iovcnt].iov_base = (char *) ifp;
        iov[iovcnt].iov_len = ifp_len;
        iovcnt++;
@@ -3333,7 +3343,7 @@ h_stateRestoreHost(struct fs_dump_state * state)
     if (hdr.hcps) {
        hcps_len = hdr.hcps * sizeof(afs_int32);
        hcps = (afs_int32 *) malloc(hcps_len);
-       assert(hcps != NULL);
+       osi_Assert(hcps != NULL);
        iov[iovcnt].iov_base = (char *) hcps;
        iov[iovcnt].iov_len = hcps_len;
        iovcnt++;
@@ -3354,11 +3364,12 @@ h_stateRestoreHost(struct fs_dump_state * state)
     if (!hdr.hcps && hdsk.hcps_valid) {
        /* valid, zero-length host cps ; does this ever happen? */
        hcps = (afs_int32 *) malloc(sizeof(afs_int32));
-       assert(hcps != NULL);
+       osi_Assert(hcps != NULL);
     }
 
+    /* for restoring state, we better be able to get a host! */
     host = GetHT();
-    assert(host != NULL);
+    osi_Assert(host != NULL);
 
     if (ifp) {
        host->interface = ifp;
@@ -3813,7 +3824,7 @@ CheckHost(struct host *host, int flags, void *rock)
 #endif
 
 int
-CheckHost_r(struct host *host, int flags, void *dummy)
+CheckHost_r(struct host *host, void *dummy)
 {
     struct client *client;
     struct rx_connection *cb_conn = NULL;
@@ -3824,7 +3835,7 @@ CheckHost_r(struct host *host, int flags, void *dummy)
     FS_STATE_RDLOCK;
     if (fs_state.mode == FS_MODE_SHUTDOWN) {
        FS_STATE_UNLOCK;
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
     FS_STATE_UNLOCK;
 #endif
@@ -3839,6 +3850,7 @@ CheckHost_r(struct host *host, int flags, void *dummy)
     if (host->LastCall < checktime) {
        h_Lock_r(host);
        if (!(host->hostFlags & HOSTDELETED)) {
+           host->hostFlags |= HWHO_INPROGRESS;
            cb_conn = host->callback_rxcon;
            rx_GetConnection(cb_conn);
            if (host->LastCall < clientdeletetime) {
@@ -3906,10 +3918,11 @@ CheckHost_r(struct host *host, int flags, void *dummy)
            rx_PutConnection(cb_conn);
            cb_conn=NULL;
            H_LOCK;
+           host->hostFlags &= ~HWHO_INPROGRESS;
        }
        h_Unlock_r(host);
     }
-    return flags;
+    return 0;
 
 }                              /*CheckHost_r */
 
@@ -3961,8 +3974,8 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
     char uuidstr[128];
     afs_uint16 port7001 = htons(7001);
 
-    assert(host);
-    assert(interf);
+    osi_Assert(host);
+    osi_Assert(interf);
 
     number = interf->numberOfInterfaces;
     myAddr = host->host;       /* current interface address */
@@ -4037,16 +4050,14 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
            malloc(sizeof(struct Interface) +
                   (sizeof(struct AddrPort) * (count - 1)));
        if (!interface) {
-           ViceLog(0, ("Failed malloc in initInterfaceAddr_r 1\n"));
-           assert(0);
+           ViceLogThenPanic(0, ("Failed malloc in initInterfaceAddr_r 1\n"));
        }
        interface->numberOfInterfaces = count;
     } else {
        interface = (struct Interface *)
            malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * count));
        if (!interface) {
-           ViceLog(0, ("Failed malloc in initInterfaceAddr_r 2\n"));
-           assert(0);
+           ViceLogThenPanic(0, ("Failed malloc in initInterfaceAddr_r 2\n"));
        }
        interface->numberOfInterfaces = count + 1;
        interface->interface[count].addr = myAddr;
@@ -4068,7 +4079,7 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
 
     interface->uuid = interf->uuid;
 
-    assert(!host->interface);
+    osi_Assert(!host->interface);
     host->interface = interface;
 
     if (LogLevel >= 125) {
@@ -4099,7 +4110,7 @@ h_DeleteHostFromAddrHashTable_r(afs_uint32 addr, afs_uint16 port,
 
     for (hp = &hostAddrHashTable[h_HashIndex(addr)]; (th = *hp);
         hp = &th->next) {
-        assert(th->hostPtr);
+        osi_Assert(th->hostPtr);
         if (th->hostPtr == host && th->addr == addr && th->port == port) {
            ViceLog(125, ("h_DeleteHostFromAddrHashTable_r: host %" AFS_PTR_FMT " (%s:%d)\n",
                          host, afs_inet_ntoa_r(host->host, hoststr),