afs: Avoid creating unused conns
[openafs.git] / src / afs / afs_server.c
index c51bf3e..d4893b1 100644 (file)
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 
 #if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
-#include <netinet/in_var.h>
-#endif /* AFS_HPUX110_ENV */
-#ifdef AFS_DARWIN_ENV
-#include <net/if_var.h>
-#endif
+# if !defined(AFS_LINUX20_ENV)
+#  include <net/if.h>
+# endif
+# include <netinet/in.h>
+
+# ifdef AFS_SGI62_ENV
+#  include "h/hashing.h"
+# endif
+# if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
+#  include <netinet/in_var.h>
+# endif /* AFS_HPUX110_ENV */
+# ifdef AFS_DARWIN_ENV
+#  include <net/if_var.h>
+# endif
 #endif /* !defined(UKERNEL) */
 
 #include "afsincludes.h"       /* Afs-based standard headers */
 #include "afs/afs_stats.h"     /* afs statistics */
 #include "rx/rx_multi.h"
 
-#if    defined(AFS_SUN5_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#include <netinet/ip6.h>
-#define ipif_local_addr ipif_lcl_addr
-#ifndef V4_PART_OF_V6
-# define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
-#endif
-#include <inet/ip.h>
+#if defined(AFS_SUN5_ENV)
+# include <inet/led.h>
+# include <inet/common.h>
+# include <netinet/ip6.h>
+# define ipif_local_addr ipif_lcl_addr
+# ifndef V4_PART_OF_V6
+#  define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
+# endif
+# include <inet/ip.h>
 #endif
 
 /* Exported variables */
@@ -129,7 +129,7 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
 {
     struct server *a_serverP = sa->server;
     struct srvAddr *sap;
-    osi_timeval_t currTime, *currTimeP;        /*Current time */
+    osi_timeval32_t currTime, *currTimeP;      /*Current time */
     afs_int32 downTime;                /*Computed downtime, in seconds */
     struct afs_stats_SrvUpDownInfo *upDownP;   /*Ptr to up/down info record */
 
@@ -172,7 +172,7 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
      * updated; we'll need them one way or another.
      */
     currTimeP = &currTime;
-    osi_GetuTime(currTimeP);
+    osi_GetTime(currTimeP);
 
     upDownP = GetUpDownStats(a_serverP);
 
@@ -230,7 +230,7 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
 
 
 afs_int32
-afs_ServerDown(struct srvAddr *sa, int code)
+afs_ServerDown(struct srvAddr *sa, int code, struct rx_connection *rxconn)
 {
     struct server *aserver = sa->server;
 
@@ -239,11 +239,11 @@ afs_ServerDown(struct srvAddr *sa, int code)
        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, code);
+       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, code);
+                              1, code, rxconn);
     return 1;
 }                              /*ServerDown */
 
@@ -301,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
@@ -310,18 +309,19 @@ 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, code);
+                                  " is back up", 2, code, rxconn);
        }
     }
+    afs_PutConn(tc, rxconn, SHARED_LOCK);
 
 }                              /*CheckVLServer */
 
 
 #ifndef        AFS_MINCHANGE           /* So that some can increase it in param.h */
-#define AFS_MINCHANGE 2                /* min change we'll bother with */
+# define AFS_MINCHANGE 2               /* min change we'll bother with */
 #endif
 #ifndef AFS_MAXCHANGEBACK
-#define AFS_MAXCHANGEBACK 10   /* max seconds we'll set a clock back at once */
+# define AFS_MAXCHANGEBACK 10  /* max seconds we'll set a clock back at once */
 #endif
 
 
@@ -354,8 +354,8 @@ afs_CountServers(void)
     int currIdx;               /*Curr idx into srv table */
     struct server *currSrvP;   /*Ptr to curr server record */
     afs_int32 currChainLen;    /*Length of curr hash chain */
-    osi_timeval_t currTime;    /*Current time */
-    osi_timeval_t *currTimeP;  /*Ptr to above */
+    osi_timeval32_t currTime;  /*Current time */
+    osi_timeval32_t *currTimeP;        /*Ptr to above */
     afs_int32 srvRecordAge;    /*Age of server record, in secs */
     struct afs_stats_SrvUpDownInfo *upDownP;   /*Ptr to current up/down
                                                 * info being manipulated */
@@ -400,7 +400,7 @@ afs_CountServers(void)
      * Compute the current time, used to figure out server record ages.
      */
     currTimeP = &currTime;
-    osi_GetuTime(currTimeP);
+    osi_GetTime(currTimeP);
 
     /*
      * Sweep the server hash table, tallying all we need to know.
@@ -515,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;
@@ -532,7 +535,7 @@ CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
            (tc->parent->srvr == sa)) {
            /* server back up */
            print_internet_address("afs: file server ", sa, " is back up", 2,
-                                  results[i]);
+                                  results[i], rxconns[i]);
 
            ObtainWriteLock(&afs_xserver, 244);
            ObtainWriteLock(&afs_xsrvAddr, 245);
@@ -546,7 +549,7 @@ CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
        } else {
            if (results[i] < 0) {
                /* server crashed */
-               afs_ServerDown(sa, results[i]);
+               afs_ServerDown(sa, results[i], rxconns[i]);
                ForceNewConnections(sa);  /* multi homed clients */
            }
        }
@@ -597,7 +600,7 @@ CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
                caps[i].Capabilities_len = 0;
            }
     }
-    CkSrv_MarkUpDown(conns, nconns, results);
+    CkSrv_MarkUpDown(conns, rxconns, nconns, results);
 
     afs_osi_Free(caps, nconns * sizeof(Capabilities));
     afs_osi_Free(results, nconns * sizeof(afs_int32));
@@ -620,7 +623,7 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
                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;
@@ -643,7 +646,7 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
     if (AFS_IS_DISCONNECTED)
         return;
 
-    if ((code = afs_InitReq(&treq, afs_osi_credp)))
+    if ((code = afs_CreateReq(&treq, afs_osi_credp)))
        return;
     ObtainReadLock(&afs_xserver);      /* Necessary? */
     ObtainReadLock(&afs_xsrvAddr);
@@ -697,15 +700,20 @@ 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;
        }
 
        if (!ts->cell)          /* not really an active server, anyway, it must */
            continue;           /* have just been added by setsprefs */
 
+       if ((sa->sa_flags & SRVADDR_ISDOWN) == 0 && !afs_HaveCallBacksFrom(sa->server)) {
+           /* Server is up, and we have no active callbacks from it. */
+           continue;
+       }
+
        /* 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, 0,
                          &rxconn);
@@ -713,18 +721,16 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
        if (!tc)
            continue;
 
-       if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
-           conns[nconns]=tc;
-           rxconns[nconns]=rxconn;
-           if (sa->sa_flags & SRVADDR_ISDOWN) {
-               rx_SetConnDeadTime(rxconn, 3);
-               conntimer[nconns]=1;
-           } else {
-               conntimer[nconns]=0;
-           }
-           nconns++;
-       } else /* not holding, kill ref */
-           afs_PutConn(tc, rxconn, SHARED_LOCK);
+       conns[nconns]=tc;
+       rxconns[nconns]=rxconn;
+       if (sa->sa_flags & SRVADDR_ISDOWN) {
+           rx_SetConnDeadTime(rxconn, 3);
+           conntimer[nconns]=1;
+       } else {
+           conntimer[nconns]=0;
+       }
+       nconns++;
+
     } /* Outer loop over addrs */
 
     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
@@ -745,6 +751,7 @@ afs_LoopServers(int adown, struct cell *acellp, int vlalso,
     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_DestroyReq(treq);
 
 } /*afs_CheckServers*/
 
@@ -819,13 +826,15 @@ afs_random(void)
 
     AFS_STATCNT(afs_random);
     if (!state) {
-       osi_timeval_t t;
+       osi_timeval32_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 nybble 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 & 0x0f);
+       state += rxi_getaddr() & 0xff;
        state += (t.tv_sec & 0xff);
        for (i = 0; i < 30; i++) {
            ranstage(state);
@@ -974,9 +983,9 @@ afs_SortServers(struct server *aservers[], int count)
 #define        USEIFADDR
 
 #ifdef AFS_USERSPACE_IP_ADDR
-#ifndef afs_min
-#define afs_min(A,B) ((A)<(B)) ? (A) : (B)
-#endif
+# ifndef afs_min
+#  define afs_min(A,B) ((A)<(B)) ? (A) : (B)
+# endif
 /*
  * The IP addresses and ranks are determined by afsd (in user space) and
  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
@@ -1024,8 +1033,10 @@ 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(AFS_FBSD_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)
 {
@@ -1048,7 +1059,7 @@ afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
                sa->sa_iprank = t;
        }
     }
-#if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
+#  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))) {
@@ -1059,23 +1070,23 @@ afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
        if (sa->sa_iprank > t)
            sa->sa_iprank = t;
     }
-#endif /* IFF_POINTOPOINT */
+#  endif /* IFF_POINTOPOINT */
 }
-#endif /*(!defined(AFS_SUN5_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
+# endif /* !SUN5 && !DARWIN && !OBSD47 && !FBSD && 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
 void
 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
 {
     struct sockaddr sout;
     struct sockaddr_in *sin;
-#if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
+#  if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
     int t;
-#else
+#  else
     void *t;
-#endif
+#  endif
 
     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
     afs_uint32 serverAddr;
@@ -1128,7 +1139,7 @@ afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
            sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
        }
     }
-#ifdef  IFF_POINTTOPOINT
+#  ifdef  IFF_POINTTOPOINT
     /* check for case #4 -- point-to-point link */
     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
        && (myDstaddr == serverAddr)) {
@@ -1139,10 +1150,10 @@ afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
        if (sa->sa_iprank > t)
            sa->sa_iprank = t;
        }
-#endif /* IFF_POINTTOPOINT */
+#  endif /* IFF_POINTTOPOINT */
 }
-#endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#endif /* else AFS_USERSPACE_IP_ADDR */
+# endif /* (DARWIN || OBSD47 || FBSD) && USEIFADDR */
+#endif /* AFS_USERSPACE_IP_ADDR */
 
 #ifdef AFS_SGI62_ENV
 static int
@@ -1156,7 +1167,7 @@ afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
 static int
 afs_SetServerPrefs(struct srvAddr *const sa)
 {
-#if     defined(AFS_USERSPACE_IP_ADDR)
+#if defined(AFS_USERSPACE_IP_ADDR)
     int i;
 
       sa->sa_iprank = LO;
@@ -1165,19 +1176,19 @@ afs_SetServerPrefs(struct srvAddr *const sa)
                             afs_cb_interface.subnetmask[i]);
     }
 #else                          /* AFS_USERSPACE_IP_ADDR */
-#if    defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN510_ENV
+# if defined(AFS_SUN5_ENV)
+#  ifdef AFS_SUN510_ENV
     int i = 0;
-#else
+#  else
     extern struct ill_s *ill_g_headp;
     long *addr = (long *)ill_g_headp;
     ill_t *ill;
     ipif_t *ipif;
-#endif
+#  endif
     int subnet, subnetmask, net, netmask;
 
     sa->sa_iprank = 0;
-#ifdef AFS_SUN510_ENV
+#  ifdef AFS_SUN510_ENV
     rw_enter(&afsifinfo_lock, RW_READER);
 
     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
@@ -1221,7 +1232,9 @@ afs_SetServerPrefs(struct srvAddr *const sa)
     }
 
     rw_exit(&afsifinfo_lock);
-#else
+
+#  else /* AFS_SUN510_ENV */
+
     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
         ill = ill->ill_next) {
        /* Make sure this is an IPv4 ILL */
@@ -1271,9 +1284,9 @@ afs_SetServerPrefs(struct srvAddr *const sa)
            }
        }
     }
-#endif /* AFS_SUN510_ENV */
-#else
-#ifndef USEIFADDR
+#  endif /* AFS_SUN510_ENV */
+# else /* AFS_SUN5_ENV */
+#  ifndef USEIFADDR
     rx_ifnet_t ifn = NULL;
     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
     struct sockaddr_in *sin;
@@ -1281,26 +1294,26 @@ afs_SetServerPrefs(struct srvAddr *const sa)
     sa->sa_iprank = 0;
     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
     if (ifn) {                 /* local, more or less */
-#ifdef IFF_LOOPBACK
+#   ifdef IFF_LOOPBACK
        if (ifn->if_flags & IFF_LOOPBACK) {
            sa->sa_iprank = TOPR;
            goto end;
        }
-#endif /* IFF_LOOPBACK */
+#   endif /* IFF_LOOPBACK */
        sin = (struct sockaddr_in *)IA_SIN(ifad);
        if (SA2ULONG(sin) == sa->sa_ip) {
            sa->sa_iprank = TOPR;
            goto end;
        }
-#ifdef IFF_BROADCAST
+#   ifdef IFF_BROADCAST
        if (ifn->if_flags & IFF_BROADCAST) {
            if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
                sa->sa_iprank = HI;
                goto end;
            }
        }
-#endif /* IFF_BROADCAST */
-#ifdef IFF_POINTOPOINT
+#   endif /* IFF_BROADCAST */
+#   ifdef IFF_POINTOPOINT
        if (ifn->if_flags & IFF_POINTOPOINT) {
            if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
                if (ifn->if_metric > 4) {
@@ -1310,16 +1323,16 @@ afs_SetServerPrefs(struct srvAddr *const sa)
                    sa->sa_iprank = ifn->if_metric;
            }
        }
-#endif /* IFF_POINTOPOINT */
+#   endif /* IFF_POINTOPOINT */
        sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
     }
-#else                          /* USEIFADDR */
+#  else /* USEIFADDR */
 
     sa->sa_iprank = LO;
-#ifdef AFS_SGI62_ENV
+#   ifdef AFS_SGI62_ENV
     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
                    (caddr_t) sa, NULL);
-#elif defined(AFS_DARWIN80_ENV)
+#   elif defined(AFS_DARWIN80_ENV)
     {
        errno_t t;
        unsigned int count;
@@ -1340,7 +1353,7 @@ afs_SetServerPrefs(struct srvAddr *const sa)
            ifnet_list_free(ifns);
        }
     }
-#elif defined(AFS_DARWIN_ENV)
+#   elif defined(AFS_DARWIN_ENV)
     {
        rx_ifnet_t ifn;
        rx_ifaddr_t ifa;
@@ -1348,43 +1361,45 @@ afs_SetServerPrefs(struct srvAddr *const sa)
            TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
                afsi_SetServerIPRank(sa, ifa);
     }}}
-#elif defined(AFS_FBSD_ENV)
+#   elif defined(AFS_FBSD_ENV)
     {
        struct in_ifaddr *ifa;
-#if defined(AFS_FBSD80_ENV)
-         TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
-#else
-         TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
-#endif
+       struct rm_priotracker in_ifa_tracker;
+       CURVNET_SET(rx_socket->so_vnet);
+       IN_IFADDR_RLOCK(&in_ifa_tracker);
+       AFS_FBSD_NET_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
            afsi_SetServerIPRank(sa, &ifa->ia_ifa);
-    }}
-#elif defined(AFS_OBSD_ENV)
+       }
+       IN_IFADDR_RUNLOCK(&in_ifa_tracker);
+       CURVNET_RESTORE();
+    }
+#   elif defined(AFS_OBSD_ENV)
     {
        extern struct in_ifaddrhead in_ifaddr;
        struct in_ifaddr *ifa;
        for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
            afsi_SetServerIPRank(sa, ifa);
     }
-#elif defined(AFS_NBSD40_ENV)
+#   elif defined(AFS_NBSD40_ENV)
      {
        extern struct in_ifaddrhead in_ifaddrhead;
        struct in_ifaddr *ifa;
        for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
            afsi_SetServerIPRank(sa, ifa);
      }
-#else
+#   else
     {
        struct in_ifaddr *ifa;
        for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
            afsi_SetServerIPRank(sa, ifa);
     }}
-#endif
-#endif                         /* USEIFADDR */
-#ifndef USEIFADDR
+#   endif
+#  endif                               /* USEIFADDR */
+#  ifndef USEIFADDR
     end:
-#endif
-#endif                         /* AFS_SUN5_ENV */
-#endif                         /* else AFS_USERSPACE_IP_ADDR */
+#  endif
+# endif                                /* AFS_SUN5_ENV */
+#endif                         /* AFS_USERSPACE_IP_ADDR */
     sa->sa_iprank += afs_randomMod15();
 
     return 0;
@@ -1488,7 +1503,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;
@@ -1499,29 +1514,36 @@ 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, 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);
+    AFS_GUNLOCK();
     code = RXAFS_GetCapabilities(rxconn, &caps);
+    AFS_GLOCK();
     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, code);
+       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;
     }
 
@@ -1534,6 +1556,7 @@ afs_GetCapabilities(struct server *ts)
        caps.Capabilities_val = NULL;
     }
 
+    afs_DestroyReq(treq);
 }
 
 static struct server *
@@ -1667,7 +1690,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++) {
@@ -1756,7 +1780,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
@@ -1785,8 +1810,6 @@ afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
        if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
            afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
     }
-    /* We can't need this below, and won't reacquire */
-    ReleaseWriteLock(&afs_xvcb);
 
     ReleaseWriteLock(&afs_xsrvAddr);
 
@@ -1800,8 +1823,8 @@ afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
 void
 afs_ActivateServer(struct srvAddr *sap)
 {
-    osi_timeval_t currTime;    /*Filled with current time */
-    osi_timeval_t *currTimeP;  /*Ptr to above */
+    osi_timeval32_t currTime;  /*Filled with current time */
+    osi_timeval32_t *currTimeP;        /*Ptr to above */
     struct afs_stats_SrvUpDownInfo *upDownP;   /*Ptr to up/down info record */
     struct server *aserver = sap->server;
 
@@ -1812,7 +1835,7 @@ afs_ActivateServer(struct srvAddr *sap)
         */
        aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
        currTimeP = &currTime;
-       osi_GetuTime(currTimeP);
+       osi_GetTime(currTimeP);
        aserver->activationTime = currTime.tv_sec;
        upDownP = GetUpDownStats(aserver);
        if (aserver->flags & SRVR_ISDOWN) {