struct server *aserver = sa->server;
struct afs_conn *tc;
afs_int32 code;
+ struct rx_connection *rxconn;
AFS_STATCNT(CheckVLServer);
/* Ping dead servers to see if they're back */
return; /* can't do much */
tc = afs_ConnByHost(aserver, aserver->cell->vlport,
- aserver->cell->cellNum, areq, 1, SHARED_LOCK);
+ aserver->cell->cellNum, areq, 1, SHARED_LOCK, &rxconn);
if (!tc)
return;
- rx_SetConnDeadTime(tc->id, 3);
+ rx_SetConnDeadTime(rxconn, 3);
RX_AFS_GUNLOCK();
- code = VL_ProbeServer(tc->id);
+ code = VL_ProbeServer(rxconn);
RX_AFS_GLOCK();
- rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
- afs_PutConn(tc, SHARED_LOCK);
+ 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
}
}
+static void
+CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
+{
+ struct srvAddr *sa;
+ struct afs_conn *tc;
+ afs_int32 i;
+
+ for(i = 0; i < nconns; i++){
+ tc = conns[i];
+ sa = tc->parent->srvr;
+
+ 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);
+
+ ObtainWriteLock(&afs_xserver, 244);
+ ObtainWriteLock(&afs_xsrvAddr, 245);
+ afs_MarkServerUpOrDown(sa, 0);
+ ReleaseWriteLock(&afs_xsrvAddr);
+ ReleaseWriteLock(&afs_xserver);
+
+ if (afs_waitForeverCount) {
+ afs_osi_Wakeup(&afs_waitForever);
+ }
+ } else {
+ if (results[i] < 0) {
+ /* server crashed */
+ afs_ServerDown(sa);
+ ForceNewConnections(sa); /* multi homed clients */
+ }
+ }
+ }
+}
+
+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)
+{
+ Capabilities *caps;
+ afs_int32 *results;
+ afs_int32 i;
+ struct server *ts;
+
+ caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
+ osi_Assert(caps != NULL);
+ memset(caps, 0, nservers * sizeof(Capabilities));
+
+ results = afs_osi_Alloc(nservers * sizeof (afs_int32));
+ osi_Assert(results != NULL);
+
+ AFS_GUNLOCK();
+ multi_Rx(rxconns,nconns)
+ {
+ multi_RXAFS_GetCapabilities(&caps[multi_i]);
+ results[multi_i] = multi_error;
+ } multi_End;
+ AFS_GLOCK();
+
+ for ( i = 0 ; i < nconns ; i++ ) {
+ ts = addrs[i]->server;
+ if ( !ts )
+ continue;
+ ts->capabilities = 0;
+ ts->flags |= SCAPS_KNOWN;
+ if ( results[i] == RXGEN_OPCODE ) {
+ /* Mark server as up - it responded */
+ results[i] = 0;
+ continue;
+ }
+ if ( results[i] >= 0 )
+ /* we currently handle 32-bits of capabilities */
+ if (caps[i].Capabilities_len > 0) {
+ ts->capabilities = caps[i].Capabilities_val[0];
+ xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
+ caps[i].Capabilities_val = NULL;
+ caps[i].Capabilities_len = 0;
+ }
+ }
+ CkSrv_MarkUpDown(conns, nconns, results);
+
+ afs_osi_Free(caps, nservers * sizeof(Capabilities));
+ afs_osi_Free(results, nservers * 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);
+}
+
+/* adown: AFS_LS_UP - check only up
+ * AFS_LS_DOWN - check only down.
+ * 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))
+{
struct vrequest treq;
struct server *ts;
struct srvAddr *sa;
- struct afs_conn *tc;
+ struct afs_conn *tc = NULL;
afs_int32 i, j;
afs_int32 code;
- afs_int32 start, end = 0, delta;
- osi_timeval_t tv;
struct unixuser *tu;
- char tbuffer[CVBS];
int srvAddrCount;
struct srvAddr **addrs;
struct afs_conn **conns;
int nconns;
struct rx_connection **rxconns;
- afs_int32 *conntimer, *deltas, *results;
- Capabilities *caps = NULL;
+ afs_int32 *conntimer, *results;
AFS_STATCNT(afs_CheckServers);
osi_Assert(rxconns != NULL);
conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
osi_Assert(conntimer != NULL);
- deltas = afs_osi_Alloc(j * sizeof (afs_int32));
- osi_Assert(deltas != NULL);
results = afs_osi_Alloc(j * sizeof (afs_int32));
osi_Assert(results != NULL);
- caps = afs_osi_Alloc(j * sizeof (Capabilities));
- osi_Assert(caps != NULL);
- memset(caps, 0, j * sizeof(Capabilities));
-
for (i = 0; i < j; i++) {
- deltas[i] = 0;
+ struct rx_connection *rxconn;
sa = addrs[i];
ts = sa->server;
if (!ts)
if (acellp && acellp != ts->cell)
continue;
- if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
- || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
+ if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
+ || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
continue;
/* check vlserver with special code */
if (sa->sa_portal == AFS_VLPORT) {
- CheckVLServer(sa, &treq);
+ if (vlalso)
+ CheckVLServer(sa, &treq);
continue;
}
/* get a connection, even if host is down; bumps conn ref count */
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);
+ 1 /*force */ , 1 /*create */ , SHARED_LOCK, &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)) {
conns[nconns]=tc;
- rxconns[nconns]=tc->id;
+ rxconns[nconns]=rxconn;
if (sa->sa_flags & SRVADDR_ISDOWN) {
- rx_SetConnDeadTime(tc->id, 3);
+ rx_SetConnDeadTime(rxconn, 3);
conntimer[nconns]=1;
} else {
conntimer[nconns]=0;
}
} /* Outer loop over addrs */
- AFS_GUNLOCK();
- multi_Rx(rxconns,nconns)
- {
- multi_RXAFS_GetCapabilities(&caps[multi_i]);
- results[multi_i] = multi_error;
- } multi_End;
- AFS_GLOCK();
+ (*func1)(rxconns, nconns, j, conns, addrs);
- for ( i = 0 ; i < nconns ; i++ ) {
- ts = addrs[i]->server;
- if ( !ts )
- continue;
- ts->capabilities = 0;
- ts->flags |= SCAPS_KNOWN;
- if ( results[i] == RXGEN_OPCODE ) {
- /* Mark server as up - it responded */
- results[i] = 0;
- continue;
- }
- if ( results[i] >= 0 )
- /* we currently handle 32-bits of capabilities */
- if (caps[i].Capabilities_len > 0) {
- ts->capabilities = caps[i].Capabilities_val[0];
- xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
- caps[i].Capabilities_val = NULL;
- caps[i].Capabilities_len = 0;
- }
- }
-
- if ( afs_setTime != 0 ) {
- 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(tc->id, 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 < j ; 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();
- }
-
- for(i=0;i<nconns;i++){
- tc = conns[i];
- sa = tc->parent->srvr;
-
- 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);
-
- ObtainWriteLock(&afs_xserver, 244);
- ObtainWriteLock(&afs_xsrvAddr, 245);
- afs_MarkServerUpOrDown(sa, 0);
- ReleaseWriteLock(&afs_xsrvAddr);
- ReleaseWriteLock(&afs_xserver);
-
- if (afs_waitForeverCount) {
- afs_osi_Wakeup(&afs_waitForever);
- }
- } else {
- if ((results[i] < 0) && (results[i] != RXGEN_OPCODE)) {
- /* server crashed */
- afs_ServerDown(sa);
- ForceNewConnections(sa); /* multi homed clients */
- }
- }
+ if (func2) {
+ (*func2)(rxconns, nconns, j, conns, addrs);
}
- /*
- * 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;
- }
- }
- }
- }
for (i = 0; i < nconns; i++) {
- afs_PutConn(conns[i], SHARED_LOCK); /* done with it now */
+ if (conntimer[i] == 1)
+ rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
+ 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(deltas, j * sizeof(afs_int32));
afs_osi_Free(results, j * sizeof(afs_int32));
- afs_osi_Free(caps, j * sizeof(Capabilities));
} /*afs_CheckServers*/
struct vrequest treq;
struct afs_conn *tc;
struct unixuser *tu;
+ struct rx_connection *rxconn;
afs_int32 code;
if ( !ts || !ts->cell )
if ( !tu )
return;
tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
- SHARED_LOCK);
+ SHARED_LOCK,
+ &rxconn);
+ afs_PutUser(tu, SHARED_LOCK);
if ( !tc )
return;
/* InitCallBackStateN, triggered by our RPC, may need this */
ReleaseWriteLock(&afs_xserver);
- code = RXAFS_GetCapabilities(tc->id, &caps);
+ 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);
ForceNewConnections(tc->parent->srvr); /* multi homed clients */
}
- afs_PutConn(tc, SHARED_LOCK);
+ 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! */
{
struct server *oldts = 0, *ts, *newts, *orphts = 0;
struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
- u_short fsport;
afs_int32 iphash, k, srvcount = 0;
unsigned int srvhash;
if (acell)
newts->cell = afs_GetCell(acell, 0);
- fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
-
/* For each IP address we are registering */
for (k = 0; k < nservers; k++) {
iphash = SHash(aserverp[k]);