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) {
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)
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)
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 */
/* 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)))
*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;
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.
* 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 */
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);
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)