afs: restore force_if_down check when getting connections
[openafs.git] / src / afs / afs_conn.c
index 0bfb526..56515c8 100644 (file)
@@ -134,7 +134,7 @@ release_conns_user_server(struct unixuser *xu, struct server *xs)
     int cix, glocked;
     struct srvAddr *sa;
     struct afs_conn *tc;
-    struct sa_conn_vector *tcv, **lcv;
+    struct sa_conn_vector *tcv, **lcv, *tcvn;
     for (sa = (xs)->addr; sa; sa = sa->next_sa) {
         lcv = &sa->conns;
         for (tcv = *lcv; tcv; lcv = &tcv->next, tcv = *lcv) {
@@ -149,6 +149,23 @@ release_conns_user_server(struct unixuser *xu, struct server *xs)
                     if (tc->activated) {
                         rx_SetConnSecondsUntilNatPing(tc->id, 0);
                         rx_DestroyConnection(tc->id);
+                       /* find another eligible connection */
+                       if (sa->natping == tc) {
+                           int cin;
+                           struct afs_conn *tcn;
+                           for (tcvn = sa->conns; tcvn; tcvn = tcvn->next) {
+                               if (tcvn == tcv)
+                                   continue;
+                               for(cin = 0; cin < CVEC_LEN; ++cin) {
+                                   tcn = &(tcvn->cvec[cin]);
+                                   if (tcn->activated) {
+                                       rx_SetConnSecondsUntilNatPing(tcn->id, 20);
+                                       sa->natping = tcn;
+                                       break;
+                                   }
+                               }
+                           }
+                       }
                     }
                 }
                 if (glocked)
@@ -163,14 +180,15 @@ release_conns_user_server(struct unixuser *xu, struct server *xs)
 
 
 static void
-release_conns_vector(struct sa_conn_vector *xcv)
+release_conns_vector(struct sa_conn_vector *tcv)
 {
     int cix, glocked;
     struct afs_conn *tc;
-    struct sa_conn_vector *tcv = NULL;
-    struct sa_conn_vector **lcv = NULL;
-    for (tcv = xcv; tcv; lcv = &tcv->next, tcv = *lcv) {
-        *lcv = tcv->next;
+    struct sa_conn_vector *next;
+
+    while (tcv != NULL) {
+       next = tcv->next;
+
         /* you know it, you love it, the GLOCK */
         glocked = ISAFS_GLOCK();
         if (glocked)
@@ -180,11 +198,14 @@ release_conns_vector(struct sa_conn_vector *xcv)
             if (tc->activated) {
                 rx_SetConnSecondsUntilNatPing(tc->id, 0);
                 rx_DestroyConnection(tc->id);
+               if (tcv->srvr->natping == tc)
+                   tcv->srvr->natping = NULL;
             }
         }
         if (glocked)
             AFS_GLOCK();
         afs_osi_Free(tcv, sizeof(struct sa_conn_vector));
+       tcv = next;
     }
 
 }        /* release_conns_vector */
@@ -282,6 +303,7 @@ afs_Conn(struct VenusFid *afid, struct vrequest *areq,
 
     /* First is always lowest rank, if it's up */
     if ((tv->status[0] == not_busy) && tv->serverHost[0]
+       && tv->serverHost[0]->addr
        && !(tv->serverHost[0]->addr->sa_flags & SRVR_ISDOWN) &&
        !(((areq->idleError > 0) || (areq->tokenError > 0))
          && (areq->skipserver[0] == 1)))
@@ -371,6 +393,11 @@ afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
 
     *rxconn = NULL;
 
+    if (!sap || ((sap->sa_flags & SRVR_ISDOWN) && !force_if_down)) {
+       /* sa is known down, and we don't want to force it.  */
+       return NULL;
+    }
+
     /* find cached connection */
     ObtainSharedLock(&afs_xconn, 15);
     foundvec = 0;
@@ -431,6 +458,18 @@ afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
         return NULL;
     }
 
+    if (tc->refCount > 10000) {
+       static int warned;
+       if (!warned) {
+           warned = 1;
+           afs_warn("afs: Very high afs_conn refCount detected (conn %p, count %d)\n",
+                    tc, (int)tc->refCount);
+           afs_warn("afs: Trying to continue, but this may indicate an issue\n");
+           afs_warn("afs: that may eventually crash the machine. Please file\n");
+           afs_warn("afs: a bug report.\n");
+       }
+    }
+
     if (tu->states & UTokensBad) {
        /* we may still have an authenticated RPC connection here,
         * we'll have to create a new, unauthenticated, connection.
@@ -439,7 +478,7 @@ afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
         * bad, but that's somewhat trickier, due to locking
         * constraints (though not impossible).
         */
-       if (tc->id && (rx_SecurityClassOf(tc->id) != 0)) {
+       if (tc->id && (rx_SecurityClassOf(tc->id) != RX_SECIDX_NULL)) {
            tc->forceConnectFS = 1;     /* force recreation of connection */
        }
        tu->states &= ~UHasTokens;      /* remove the authentication info */
@@ -448,8 +487,9 @@ afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
     glocked = ISAFS_GLOCK();
     if (tc->forceConnectFS) {
        UpgradeSToWLock(&afs_xconn, 38);
-       csec = (struct rx_securityClass *)0;
        if (tc->id) {
+           if (sap->natping == tc)
+               sap->natping = NULL;
            if (glocked)
                 AFS_GUNLOCK();
             rx_SetConnSecondsUntilNatPing(tc->id, 0);
@@ -478,23 +518,20 @@ afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
            rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
        }
 
-        /* Setting idle dead time to non-zero activates RX_CALL_IDLE errors. */
+        /* Setting idle dead time to non-zero activates idle-dead
+        * RX_CALL_TIMEOUT errors. */
        if (isrep)
            rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead_rep);
        else
            rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead);
 
        /*
-        * Only do this for the base connection, not per-user.
-        * Will need to be revisited if/when CB gets security.
+        * Only do this for one connection
         */
-       if ((isec == 0) && (service != 52) && !(tu->states & UTokensBad) &&
-           (tu->viceId == UNDEFVID) && (isrep == 0)
-#ifndef UKERNEL /* ukernel runs as just one uid anyway */
-           && (tu->uid == 0)
-#endif
-           )
+       if ((service != 52) && (sap->natping == NULL)) {
+           sap->natping = tc;
            rx_SetConnSecondsUntilNatPing(tc->id, 20);
+       }
 
        tc->forceConnectFS = 0; /* apparently we're appropriately connected now */
        if (csec)