/* Exported variables */
afs_rwlock_t afs_xconn; /* allocation lock for new things */
afs_rwlock_t afs_xinterface; /* for multiple client address */
-afs_int32 cryptall = 0; /* encrypt all communications */
+afs_int32 cryptall = 1; /* encrypt all communications */
/* some connection macros */
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 */
int notbusy;
int i;
struct srvAddr *sa1p;
+ afs_int32 replicated = -1; /* a single RO will increment to 0 */
*rxconn = NULL;
/* 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)))
*/
for (notbusy = not_busy; (!lowp && (notbusy <= end_not_busy)); notbusy++) {
for (i = 0; i < AFS_MAXHOSTS && tv->serverHost[i]; i++) {
+ if (tv->states & VRO)
+ replicated++;
if (((areq->tokenError > 0)||(areq->idleError > 0))
&& (areq->skipserver[i] == 1))
continue;
}
}
}
+ if ((replicated == -1) && (tv->states & VRO)) {
+ for (i = 0; i < AFS_MAXHOSTS && tv->serverHost[i]; i++) {
+ if (tv->states & VRO)
+ replicated++;
+ }
+ } else
+ replicated = 0;
+
afs_PutVolume(tv, READ_LOCK);
if (lowp) {
tu = afs_GetUser(areq->uid, afid->Cell, SHARED_LOCK);
tconn = afs_ConnBySA(lowp, fsport, afid->Cell, tu, 0 /*!force */ ,
- 1 /*create */ , locktype, rxconn);
+ 1 /*create */ , locktype, replicated, rxconn);
afs_PutUser(tu, SHARED_LOCK);
}
* @param tu Connect as this user.
* @param force_if_down
* @param create
+ * @param replicated
* @param locktype Specifies type of lock to be used for this function.
*
* @return The new connection.
struct afs_conn *
afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
struct unixuser *tu, int force_if_down, afs_int32 create,
- afs_int32 locktype, struct rx_connection **rxconn)
+ afs_int32 locktype, afs_int32 replicated,
+ struct rx_connection **rxconn)
{
int glocked, foundvec;
struct afs_conn *tc = NULL;
struct rx_securityClass *csec; /*Security class object */
int isec; /*Security index */
int service;
+ int isrep = (replicated > 0)?CONN_REPLICATED:0;
*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;
for (tcv = sap->conns; tcv; tcv = tcv->next) {
- if (tcv->user == tu && tcv->port == aport) {
+ if (tcv->user == tu && tcv->port == aport &&
+ (isrep == (tcv->flags & CONN_REPLICATED))) {
/* return most eligible conn */
if (!foundvec)
foundvec = 1;
tcv->port = aport;
tcv->srvr = sap;
tcv->next = sap->conns;
+ if (isrep)
+ tcv->flags |= CONN_REPLICATED;
sap->conns = tcv;
/* all struct afs_conn ptrs come from here */
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);
if (service == 52) {
rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
}
- /* set to a RX_CALL_TIMEOUT error to allow MTU retry to trigger */
- rx_SetServerConnIdleDeadErr(tc->id, RX_CALL_DEAD);
- rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead);
+
+ /* 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) && (tu->uid == 0))
+ 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)
* @param areq The request.
* @param aforce Force connection?
* @param locktype Type of lock to be used.
+ * @param replicated
*
* @return The established connection.
*/
struct afs_conn *
afs_ConnByHost(struct server *aserver, unsigned short aport, afs_int32 acell,
struct vrequest *areq, int aforce, afs_int32 locktype,
- struct rx_connection **rxconn)
+ afs_int32 replicated, struct rx_connection **rxconn)
{
struct unixuser *tu;
struct afs_conn *tc = NULL;
for (sa = aserver->addr; sa; sa = sa->next_sa) {
tc = afs_ConnBySA(sa, aport, acell, tu, aforce,
0 /*don't create one */ ,
- locktype, rxconn);
+ locktype, replicated, rxconn);
if (tc)
break;
}
for (sa = aserver->addr; sa; sa = sa->next_sa) {
tc = afs_ConnBySA(sa, aport, acell, tu, aforce,
1 /*create one */ ,
- locktype, rxconn);
+ locktype, replicated, rxconn);
if (tc)
break;
}
* @param acell The cell where all of this happens.
* @param areq The request.
* @param locktype Type of lock to be used.
+ * @param replicated
*
* @return The established connection or NULL.
*/
struct afs_conn *
afs_ConnByMHosts(struct server *ahosts[], unsigned short aport,
afs_int32 acell, struct vrequest *areq,
- afs_int32 locktype, struct rx_connection **rxconn)
+ afs_int32 locktype, afs_int32 replicated,
+ struct rx_connection **rxconn)
{
afs_int32 i;
struct afs_conn *tconn;
for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
if ((ts = ahosts[i]) == NULL)
break;
- tconn = afs_ConnByHost(ts, aport, acell, areq, 0, locktype, rxconn);
+ tconn = afs_ConnByHost(ts, aport, acell, areq, 0, locktype,
+ replicated, rxconn);
if (tconn) {
return tconn;
}
AFS_STATCNT(afs_PutConn);
ac->refCount--;
if (ac->refCount < 0) {
- static int warned = 0;
- /* So, someone is 'put'ing more refs than they got. From now on, we
- * have no idea if the structure is actually still in use, so just
- * set the refcount to a really negative number to make it unlikely
- * that the count will ever reach 0 and the conn gets freed. This
- * leaks memory, but the alternative is panicing, or risking memory
- * corruption. */
- ac->refCount = -10000;
- if (!warned) {
- warned = 1;
- afs_warn("afs_PutConn: negative refCount with 0x%lx; this should "
- "not ever happen! Trying to carry on anyway, but please "
- "report this issue\n",
- (unsigned long)(uintptrsz)ac);
- }
- return;
+ osi_Panic("afs_PutConn: refcount imbalance 0x%lx %d",
+ (unsigned long)(uintptrsz)ac, (int)ac->refCount);
}
ac->parent->refCount--;
rx_PutConnection(rxconn);