rework afs_random() yet again
[openafs.git] / src / afs / afs_server.c
index 1406ff1..d8414d6 100644 (file)
@@ -70,7 +70,6 @@
 
 /* Exported variables */
 afs_rwlock_t afs_xserver;      /* allocation lock for servers */
-struct server *afs_setTimeHost = 0;    /* last host we used for time */
 struct server *afs_servers[NSERVERS];  /* Hashed by server`s uuid & 1st ip */
 afs_rwlock_t afs_xsrvAddr;     /* allocation lock for srvAddrs */
 struct srvAddr *afs_srvAddrs[NSERVERS];        /* Hashed by server's ip */
@@ -155,11 +154,6 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
         * All ips are down we treat the whole server down
         */
        a_serverP->flags |= SRVR_ISDOWN;
-       /*
-        * If this was our time server, search for another time server
-        */
-       if (a_serverP == afs_setTimeHost)
-           afs_setTimeHost = 0;
     } else {
        sa->sa_flags &= ~SRVADDR_ISDOWN;
        /* If any ips are up, the server is also marked up */
@@ -236,7 +230,7 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
 
 
 afs_int32
-afs_ServerDown(struct srvAddr *sa)
+afs_ServerDown(struct srvAddr *sa, int code, struct rx_connection *rxconn)
 {
     struct server *aserver = sa->server;
 
@@ -245,11 +239,11 @@ afs_ServerDown(struct srvAddr *sa)
        return 0;
     afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
     if (sa->sa_portal == aserver->cell->vlport)
-       print_internet_address
-           ("afs: Lost contact with volume location server ", sa, "", 1);
+       print_internet_address("afs: Lost contact with volume location server ",
+                             sa, "", 1, code, rxconn);
     else
        print_internet_address("afs: Lost contact with file server ", sa, "",
-                              1);
+                              1, code, rxconn);
     return 1;
 }                              /*ServerDown */
 
@@ -297,7 +291,8 @@ CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
        return;                 /* can't do much */
 
     tc = afs_ConnByHost(aserver, aserver->cell->vlport,
-                       aserver->cell->cellNum, areq, 1, SHARED_LOCK, &rxconn);
+                       aserver->cell->cellNum, areq, 1, SHARED_LOCK, 0,
+                       &rxconn);
     if (!tc)
        return;
     rx_SetConnDeadTime(rxconn, 3);
@@ -306,7 +301,6 @@ CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
     code = VL_ProbeServer(rxconn);
     RX_AFS_GLOCK();
     rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
-    afs_PutConn(tc, rxconn, SHARED_LOCK);
     /*
      * If probe worked, or probe call not yet defined (for compatibility
      * with old vlsevers), then we treat this server as running again
@@ -315,9 +309,10 @@ CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
        if (tc->parent->srvr == sa) {
            afs_MarkServerUpOrDown(sa, 0);
            print_internet_address("afs: volume location server ", sa,
-                                  " is back up", 2);
+                                  " is back up", 2, code, rxconn);
        }
     }
+    afs_PutConn(tc, rxconn, SHARED_LOCK);
 
 }                              /*CheckVLServer */
 
@@ -520,10 +515,13 @@ ForceAllNewConnections(void)
         sa = addrs[i];
        ForceNewConnections(sa);
     }
+
+    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
 }
 
 static void
-CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
+CkSrv_MarkUpDown(struct afs_conn **conns, struct rx_connection **rxconns,
+                 int nconns, afs_int32 *results)
 {
     struct srvAddr *sa;
     struct afs_conn *tc;
@@ -536,7 +534,8 @@ CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
        if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
            (tc->parent->srvr == sa)) {
            /* server back up */
-           print_internet_address("afs: file server ", sa, " is back up", 2);
+           print_internet_address("afs: file server ", sa, " is back up", 2,
+                                  results[i], rxconns[i]);
 
            ObtainWriteLock(&afs_xserver, 244);
            ObtainWriteLock(&afs_xsrvAddr, 245);
@@ -550,7 +549,7 @@ CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
        } else {
            if (results[i] < 0) {
                /* server crashed */
-               afs_ServerDown(sa);
+               afs_ServerDown(sa, results[i], rxconns[i]);
                ForceNewConnections(sa);  /* multi homed clients */
            }
        }
@@ -558,151 +557,19 @@ CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
 }
 
 void
-CkSrv_SetTime(struct rx_connection **rxconns, int nconns, int nservers,
-             struct afs_conn **conns, struct srvAddr **addrs)
-{
-    struct afs_conn *tc;
-    afs_int32 start, end = 0, delta;
-    osi_timeval_t tv;
-    struct srvAddr *sa;
-    afs_int32 *conntimer, *results, *deltas;
-    afs_int32 i = 0;
-    char tbuffer[CVBS];
-
-    conntimer = afs_osi_Alloc(nservers * sizeof (afs_int32));
-    osi_Assert(conntimer != NULL);
-    results = afs_osi_Alloc(nservers * sizeof (afs_int32));
-    osi_Assert(results != NULL);
-    deltas = afs_osi_Alloc(nservers * sizeof (afs_int32));
-    osi_Assert(deltas != NULL);
-
-    /* make sure we're starting from zero */
-    memset(&deltas, 0, sizeof(deltas));
-
-    start = osi_Time();         /* time the gettimeofday call */
-    AFS_GUNLOCK();
-    if ( afs_setTimeHost == NULL ) {
-       multi_Rx(rxconns,nconns)
-       {
-           tv.tv_sec = tv.tv_usec = 0;
-           multi_RXAFS_GetTime(
-               (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
-           tc = conns[multi_i];
-           sa = tc->parent->srvr;
-           if (conntimer[multi_i] == 1)
-               rx_SetConnDeadTime(rxconns[multi_i], afs_rx_deadtime);
-           end = osi_Time();
-           results[multi_i]=multi_error;
-           if ((start == end) && !multi_error)
-               deltas[multi_i] = end - tv.tv_sec;
-       } multi_End;
-    } else {                   /* find and query setTimeHost only */
-       for ( i = 0 ; i < nservers ; i++ ) {
-           if ( conns[i] == NULL || conns[i]->parent->srvr == NULL )
-               continue;
-           if ( conns[i]->parent->srvr->server == afs_setTimeHost ) {
-               tv.tv_sec = tv.tv_usec = 0;
-               results[i] = RXAFS_GetTime(rxconns[i],
-                                          (afs_uint32 *)&tv.tv_sec,
-                                          (afs_uint32 *)&tv.tv_usec);
-               end = osi_Time();
-               if ((start == end) && !results[i])
-                   deltas[i] = end - tv.tv_sec;
-               break;
-           }
-       }
-    }
-    AFS_GLOCK();
-
-    if ( afs_setTimeHost == NULL )
-       CkSrv_MarkUpDown(conns, nconns, results);
-    else /* We lack info for other than this host */
-       CkSrv_MarkUpDown(&conns[i], 1, &results[i]);
-
-    /*
-     * If we're supposed to set the time, and the call worked
-     * quickly (same second response) and this is the host we
-     * use for the time and the time is really different, then
-     * really set the time
-     */
-    if (afs_setTime != 0) {
-       for (i=0; i<nconns; i++) {
-           delta = deltas[i];
-           tc = conns[i];
-           sa = tc->parent->srvr;
-
-           if ((tc->parent->srvr->server == afs_setTimeHost ||
-                /* Sync only to a server in the local cell */
-                (afs_setTimeHost == (struct server *)0 &&
-                 afs_IsPrimaryCell(sa->server->cell)))) {
-               /* set the time */
-               char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
-               delta = end - tv.tv_sec;   /* how many secs fast we are */
-
-               afs_setTimeHost = tc->parent->srvr->server;
-               /* see if clock has changed enough to make it worthwhile */
-               if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
-                   end = osi_Time();
-                   if (delta > AFS_MAXCHANGEBACK) {
-                       /* setting clock too far back, just do it a little */
-                       tv.tv_sec = end - AFS_MAXCHANGEBACK;
-                   } else {
-                       tv.tv_sec = end - delta;
-                   }
-                   afs_osi_SetTime(&tv);
-                   if (delta > 0) {
-                       strcpy(msgbuf, "afs: setting clock back ");
-                       if (delta > AFS_MAXCHANGEBACK) {
-                           afs_strcat(msgbuf,
-                                      afs_cv2string(&tbuffer[CVBS],
-                                                    AFS_MAXCHANGEBACK));
-                           afs_strcat(msgbuf, " seconds (of ");
-                           afs_strcat(msgbuf,
-                                      afs_cv2string(&tbuffer[CVBS],
-                                                    delta -
-                                                    AFS_MAXCHANGEBACK));
-                           afs_strcat(msgbuf, ", via ");
-                           print_internet_address(msgbuf, sa,
-                                                  "); clock is still fast.",
-                                                  0);
-                       } else {
-                           afs_strcat(msgbuf,
-                                      afs_cv2string(&tbuffer[CVBS], delta));
-                           afs_strcat(msgbuf, " seconds (via ");
-                           print_internet_address(msgbuf, sa, ").", 0);
-                       }
-                   } else {
-                       strcpy(msgbuf, "afs: setting clock ahead ");
-                       afs_strcat(msgbuf,
-                                  afs_cv2string(&tbuffer[CVBS], -delta));
-                       afs_strcat(msgbuf, " seconds (via ");
-                       print_internet_address(msgbuf, sa, ").", 0);
-                   }
-                    /* We're only going to set it once; why bother looping? */
-                   break;
-               }
-           }
-       }
-    }
-    afs_osi_Free(conntimer, nservers * sizeof(afs_int32));
-    afs_osi_Free(deltas, nservers * sizeof(afs_int32));
-    afs_osi_Free(results, nservers * sizeof(afs_int32));
-}
-
-void
-CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
-             struct afs_conn **conns, struct srvAddr **addrs)
+CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
+             struct afs_conn **conns)
 {
     Capabilities *caps;
     afs_int32 *results;
     afs_int32 i;
     struct server *ts;
 
-    caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
+    caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
     osi_Assert(caps != NULL);
-    memset(caps, 0, nservers * sizeof(Capabilities));
+    memset(caps, 0, nconns * sizeof(Capabilities));
 
-    results = afs_osi_Alloc(nservers * sizeof (afs_int32));
+    results = afs_osi_Alloc(nconns * sizeof (afs_int32));
     osi_Assert(results != NULL);
 
     AFS_GUNLOCK();
@@ -714,7 +581,7 @@ CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
     AFS_GLOCK();
 
     for ( i = 0 ; i < nconns ; i++ ) {
-       ts = addrs[i]->server;
+       ts = conns[i]->parent->srvr->server;
        if ( !ts )
            continue;
        ts->capabilities = 0;
@@ -733,18 +600,17 @@ CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
                caps[i].Capabilities_len = 0;
            }
     }
-    CkSrv_MarkUpDown(conns, nconns, results);
+    CkSrv_MarkUpDown(conns, rxconns, nconns, results);
 
-    afs_osi_Free(caps, nservers * sizeof(Capabilities));
-    afs_osi_Free(results, nservers * sizeof(afs_int32));
+    afs_osi_Free(caps, nconns * sizeof(Capabilities));
+    afs_osi_Free(results, nconns * sizeof(afs_int32));
 }
 
 /* check down servers (if adown), or running servers (if !adown) */
 void
 afs_CheckServers(int adown, struct cell *acellp)
 {
-    afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps,
-                   afs_setTime?CkSrv_SetTime:NULL);
+    afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
 }
 
 /* adown: AFS_LS_UP   - check only up
@@ -752,14 +618,12 @@ afs_CheckServers(int adown, struct cell *acellp)
  *        AFS_LS_ALL  - check all */
 void
 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
-               void (*func1) (struct rx_connection **rxconns, int nconns,
-                              int nservers, struct afs_conn **conns,
-                              struct srvAddr **addrs),
-               void (*func2) (struct rx_connection **rxconns, int nconns,
-                              int nservers, struct afs_conn **conns,
-                              struct srvAddr **addrs))
+               void (*func1) (int nservers, struct rx_connection **rxconns,
+                              struct afs_conn **conns),
+               void (*func2) (int nservers, struct rx_connection **rxconns,
+                              struct afs_conn **conns))
 {
-    struct vrequest treq;
+    struct vrequest *treq = NULL;
     struct server *ts;
     struct srvAddr *sa;
     struct afs_conn *tc = NULL;
@@ -771,7 +635,7 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
     struct afs_conn **conns;
     int nconns;
     struct rx_connection **rxconns;
-    afs_int32 *conntimer, *results;
+    afs_int32 *conntimer;
 
     AFS_STATCNT(afs_CheckServers);
 
@@ -782,12 +646,7 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
     if (AFS_IS_DISCONNECTED)
         return;
 
-    conns = (struct afs_conn **)0;
-    rxconns = (struct rx_connection **) 0;
-    conntimer = 0;
-    nconns = 0;
-
-    if ((code = afs_InitReq(&treq, afs_osi_credp)))
+    if ((code = afs_CreateReq(&treq, afs_osi_credp)))
        return;
     ObtainReadLock(&afs_xserver);      /* Necessary? */
     ObtainReadLock(&afs_xsrvAddr);
@@ -819,9 +678,8 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
     osi_Assert(rxconns != NULL);
     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
     osi_Assert(conntimer != NULL);
-    results = afs_osi_Alloc(j * sizeof (afs_int32));
-    osi_Assert(results != NULL);
 
+    nconns = 0;
     for (i = 0; i < j; i++) {
        struct rx_connection *rxconn;
        sa = addrs[i];
@@ -842,7 +700,7 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
        /* check vlserver with special code */
        if (sa->sa_portal == AFS_VLPORT) {
            if (vlalso)
-               CheckVLServer(sa, &treq);
+               CheckVLServer(sa, treq);
            continue;
        }
 
@@ -850,15 +708,15 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
            continue;           /* have just been added by setsprefs */
 
        /* get a connection, even if host is down; bumps conn ref count */
-       tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
+       tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
        tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
-                         1 /*force */ , 1 /*create */ , SHARED_LOCK, &rxconn);
+                         1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
+                         &rxconn);
        afs_PutUser(tu, SHARED_LOCK);
        if (!tc)
            continue;
 
-       if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
-           || (tc->parent->srvr->server == afs_setTimeHost)) {
+       if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
            conns[nconns]=tc;
            rxconns[nconns]=rxconn;
            if (sa->sa_flags & SRVADDR_ISDOWN) {
@@ -868,13 +726,17 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
                conntimer[nconns]=0;
            }
            nconns++;
-       }
+       } else /* not holding, kill ref */
+           afs_PutConn(tc, rxconn, SHARED_LOCK);
     } /* Outer loop over addrs */
 
-    (*func1)(rxconns, nconns, j, conns, addrs);
+    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
+    addrs = NULL;
+
+    (*func1)(nconns, rxconns, conns);
 
     if (func2) {
-       (*func2)(rxconns, nconns, j, conns, addrs);
+       (*func2)(nconns, rxconns, conns);
     }
 
     for (i = 0; i < nconns; i++) {
@@ -883,11 +745,10 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
        afs_PutConn(conns[i], rxconns[i], SHARED_LOCK);     /* done with it now */
     }
 
-    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
     afs_osi_Free(conntimer, j * sizeof(afs_int32));
-    afs_osi_Free(results, j * sizeof(afs_int32));
+    afs_DestroyReq(treq);
 
 } /*afs_CheckServers*/
 
@@ -965,10 +826,12 @@ afs_random(void)
        osi_timeval_t t;
        osi_GetTime(&t);
        /*
-        * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
-        * bits are in a tv_usec
+        * Clear the low byte of tv_usec in a size-independent manner before adding
+        * in the rest of the state.
         */
-       state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
+       state = t.tv_usec;
+       state ^= (state & 0xff);
+       state += rxi_getaddr() & 0xff;
        state += (t.tv_sec & 0xff);
        for (i = 0; i < 30; i++) {
            ranstage(state);
@@ -1168,7 +1031,7 @@ afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
     return;
 }
 #else /* AFS_USERSPACE_IP_ADDR */
-#if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
+#if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && (! defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
 void
 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
 {
@@ -1191,7 +1054,7 @@ afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
                sa->sa_iprank = t;
        }
     }
-#ifdef  IFF_POINTTOPOINT
+#if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
     /* check for case #4 -- point-to-point link */
     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
        && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
@@ -1202,10 +1065,10 @@ afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
        if (sa->sa_iprank > t)
            sa->sa_iprank = t;
     }
-#endif /* IFF_POINTTOPOINT */
+#endif /* IFF_POINTOPOINT */
 }
 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
+#if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV) || defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
 #ifndef afs_min
 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
 #endif
@@ -1214,7 +1077,11 @@ afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
 {
     struct sockaddr sout;
     struct sockaddr_in *sin;
+#if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
     int t;
+#else
+    void *t;
+#endif
 
     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
     afs_uint32 serverAddr;
@@ -1293,7 +1160,7 @@ afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
 }
 #endif                         /* AFS_SGI62_ENV */
 static int
-afs_SetServerPrefs(struct srvAddr *sa)
+afs_SetServerPrefs(struct srvAddr *const sa)
 {
 #if     defined(AFS_USERSPACE_IP_ADDR)
     int i;
@@ -1315,8 +1182,7 @@ afs_SetServerPrefs(struct srvAddr *sa)
 #endif
     int subnet, subnetmask, net, netmask;
 
-    if (sa)
-         sa->sa_iprank = 0;
+    sa->sa_iprank = 0;
 #ifdef AFS_SUN510_ENV
     rw_enter(&afsifinfo_lock, RW_READER);
 
@@ -1333,16 +1199,6 @@ afs_SetServerPrefs(struct srvAddr *sa)
        }
        net = afsifinfo[i].ipaddr & netmask;
 
-#ifdef notdef
-       if (!s) {
-           if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) {      /* ignore loopback */
-               *cnt += 1;
-               if (*cnt > 16)
-                   return;
-               *addrp++ = afsifinfo[i].ipaddr;
-           }
-       } else
-#endif /* notdef */
         {
             /* XXXXXX Do the individual ip ranking below XXXXX */
             if ((sa->sa_ip & netmask) == net) {
@@ -1394,16 +1250,6 @@ afs_SetServerPrefs(struct srvAddr *sa)
                netmask = 0;
            }
            net = ipif->ipif_local_addr & netmask;
-#ifdef notdef
-           if (!s) {
-               if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) {        /* ignore loopback */
-                   *cnt += 1;
-                   if (*cnt > 16)
-                       return;
-                   *addrp++ = ipif->ipif_local_addr;
-               }
-           } else
-#endif /* notdef */
            {
                /* XXXXXX Do the individual ip ranking below XXXXX */
                if ((sa->sa_ip & netmask) == net) {
@@ -1438,27 +1284,8 @@ afs_SetServerPrefs(struct srvAddr *sa)
     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
     struct sockaddr_in *sin;
 
-    if (!sa) {
-#ifdef notdef                  /* clean up, remove this */
-       for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
-           for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
-               if ((IFADDR2SA(ifad)->sa_family == AF_INET)
-                   && !(ifn->if_flags & IFF_LOOPBACK)) {
-                   *cnt += 1;
-                   if (*cnt > 16)
-                       return;
-                   *addrp++ =
-                       ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
-                       s_addr;
-               }
-       }}
-#endif                         /* notdef */
-       return;
-    }
     sa->sa_iprank = 0;
-#ifdef ADAPT_MTU
     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
-#endif
     if (ifn) {                 /* local, more or less */
 #ifdef IFF_LOOPBACK
        if (ifn->if_flags & IFF_LOOPBACK) {
@@ -1494,8 +1321,7 @@ afs_SetServerPrefs(struct srvAddr *sa)
     }
 #else                          /* USEIFADDR */
 
-    if (sa)
-       sa->sa_iprank = LO;
+    sa->sa_iprank = LO;
 #ifdef AFS_SGI62_ENV
     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
                    (caddr_t) sa, NULL);
@@ -1536,7 +1362,7 @@ afs_SetServerPrefs(struct srvAddr *sa)
 #else
          TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
 #endif
-           afsi_SetServerIPRank(sa, ifa);
+           afsi_SetServerIPRank(sa, &ifa->ia_ifa);
     }}
 #elif defined(AFS_OBSD_ENV)
     {
@@ -1565,8 +1391,7 @@ afs_SetServerPrefs(struct srvAddr *sa)
 #endif
 #endif                         /* AFS_SUN5_ENV */
 #endif                         /* else AFS_USERSPACE_IP_ADDR */
-    if (sa)
-         sa->sa_iprank += afs_randomMod15();
+    sa->sa_iprank += afs_randomMod15();
 
     return 0;
 }                              /* afs_SetServerPrefs */
@@ -1669,7 +1494,7 @@ void
 afs_GetCapabilities(struct server *ts)
 {
     Capabilities caps = {0, NULL};
-    struct vrequest treq;
+    struct vrequest *treq = NULL;
     struct afs_conn *tc;
     struct unixuser *tu;
     struct rx_connection *rxconn;
@@ -1680,30 +1505,34 @@ afs_GetCapabilities(struct server *ts)
     if ( !afs_osi_credp )
        return;
 
-    if ((code = afs_InitReq(&treq, afs_osi_credp)))
+    if ((code = afs_CreateReq(&treq, afs_osi_credp)))
        return;
-    tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
-    if ( !tu )
+    tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
+    if ( !tu ) {
+       afs_DestroyReq(treq);
        return;
+    }
     tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
-                                                               SHARED_LOCK,
-                                                                &rxconn);
+                     SHARED_LOCK, 0, &rxconn);
     afs_PutUser(tu, SHARED_LOCK);
-    if ( !tc )
+    if ( !tc ) {
+       afs_DestroyReq(treq);
        return;
+    }
     /* InitCallBackStateN, triggered by our RPC, may need this */
     ReleaseWriteLock(&afs_xserver);
     code = RXAFS_GetCapabilities(rxconn, &caps);
     ObtainWriteLock(&afs_xserver, 723);
     /* we forced a conn above; important we mark it down if needed */
     if ((code < 0) && (code != RXGEN_OPCODE)) {
-       afs_ServerDown(tc->parent->srvr);
+       afs_ServerDown(tc->parent->srvr, code, rxconn);
        ForceNewConnections(tc->parent->srvr); /* multi homed clients */
     }
     afs_PutConn(tc, rxconn, SHARED_LOCK);
     if ( code && code != RXGEN_OPCODE ) {
        afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
        /* better not be anything to free. we failed! */
+       afs_DestroyReq(treq);
        return;
     }
 
@@ -1716,6 +1545,7 @@ afs_GetCapabilities(struct server *ts)
        caps.Capabilities_val = NULL;
     }
 
+    afs_DestroyReq(treq);
 }
 
 static struct server *
@@ -1849,7 +1679,8 @@ afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
        newts->flags |= SRVR_MULTIHOMED;
     }
     if (acell)
-       newts->cell = afs_GetCell(acell, 0);
+       /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
+       newts->cell = afs_GetCellStale(acell, 0);
 
     /* For each IP address we are registering */
     for (k = 0; k < nservers; k++) {
@@ -1938,7 +1769,8 @@ afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
                afs_servers[iphash] = orphts;
 
                if (acell)
-                   orphts->cell = afs_GetCell(acell, 0);
+                   /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
+                   orphts->cell = afs_GetCellStale(acell, 0);
            }
 
            /* Hang the srvAddr struct off of the server structure. The server
@@ -2024,6 +1856,7 @@ afs_RemoveAllConns(void)
                 if (sa->conns) {
                     afs_ReleaseConns(sa->conns);
                     sa->conns = NULL;
+                   sa->natping = NULL;
                 }
             }
         }