/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
* afsi_SetServerIPRank
* afs_GetServer
* afs_ActivateServer
- *
+ *
*
* Local:
* HaveCallBacksFrom
* CheckVLServer
* afs_SortOneServer
* afs_SetServerPrefs
- *
+ *
*/
#include <afsconfig.h>
#include "afs/param.h"
#ifdef AFS_SGI62_ENV
#include "h/hashing.h"
#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
+#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
#include <netinet/in_var.h>
#endif /* AFS_HPUX110_ENV */
-#ifdef AFS_DARWIN60_ENV
+#ifdef AFS_DARWIN_ENV
#include <net/if_var.h>
#endif
#endif /* !defined(UKERNEL) */
void
afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
{
- register struct server *a_serverP = sa->server;
- register struct srvAddr *sap;
+ struct server *a_serverP = sa->server;
+ struct srvAddr *sap;
osi_timeval_t currTime, *currTimeP; /*Current time */
afs_int32 downTime; /*Computed downtime, in seconds */
struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
return;
}
}
- /*
+ /*
* All ips are down we treat the whole server down
*/
a_serverP->flags |= SRVR_ISDOWN;
afs_int32
afs_ServerDown(struct srvAddr *sa)
{
- register struct server *aserver = sa->server;
+ struct server *aserver = sa->server;
AFS_STATCNT(ServerDown);
- if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
+ if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
return 0;
afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
if (sa->sa_portal == aserver->cell->vlport)
int
afs_HaveCallBacksFrom(struct server *aserver)
{
- register afs_int32 now;
- register int i;
- register struct vcache *tvc;
+ afs_int32 now;
+ int i;
+ struct vcache *tvc;
AFS_STATCNT(HaveCallBacksFrom);
now = osi_Time(); /* for checking for expired callbacks */
static void
-CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
+CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
{
- register struct server *aserver = sa->server;
- register struct afs_conn *tc;
- register afs_int32 code;
+ 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
*/
if (code == 0 || (code <= -450 && code >= -470)) {
- if (tc->srvr == sa) {
+ if (tc->parent->srvr == sa) {
afs_MarkServerUpOrDown(sa, 0);
print_internet_address("afs: volume location server ", sa,
" is back up", 2);
afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
+ memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
+ memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
+ memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
- memset((char *)afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
+ memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
/*
/*
* Any further tallying for this record will only be done if it has
- * been activated.
+ * been activated.
*/
if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
&& currSrvP->addr && currSrvP->cell) {
}
addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
+ osi_Assert(addrs != NULL);
j = 0;
for (i = 0; i < NSERVERS; i++) {
for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
}
}
+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;
+ struct rx_connection **rxconns;
+ afs_int32 *conntimer, *results;
AFS_STATCNT(afs_CheckServers);
- /*
+ /*
* No sense in doing the server checks if we are running in disconnected
* mode
*/
}
addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
+ osi_Assert(addrs != NULL);
j = 0;
for (i = 0; i < NSERVERS; i++) {
for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
ReleaseReadLock(&afs_xsrvAddr);
ReleaseReadLock(&afs_xserver);
- conns = (struct afs_conn **)afs_osi_Alloc(j * sizeof(struct afs_conn *));
- rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
- conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
- deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
- results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
+ conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
+ osi_Assert(conns != NULL);
+ rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
+ osi_Assert(rxconns != NULL);
+ conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
+ osi_Assert(conntimer != NULL);
+ results = afs_osi_Alloc(j * sizeof (afs_int32));
+ osi_Assert(results != NULL);
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->srvr->server == afs_setTimeHost)) {
- conns[nconns]=tc;
- rxconns[nconns]=tc->id;
+ || (tc->parent->srvr->server == afs_setTimeHost)) {
+ conns[nconns]=tc;
+ 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 */
- start = osi_Time(); /* time the gettimeofday call */
- AFS_GUNLOCK();
- 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->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;
- AFS_GLOCK();
-
- for(i=0;i<nconns;i++){
- tc = conns[i];
- sa = tc->srvr;
-
- if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->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 */
- }
- }
- }
+ (*func1)(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->srvr;
-
- if ((tc->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->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;
- }
- }
- }
+ if (func2) {
+ (*func2)(rxconns, nconns, j, conns, addrs);
}
+
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_CheckServers*/
/* Rules:
X = (aX + c) % m
- m is a power of two
+ m is a power of two
a % 8 is 5
a is 0.73m should be 0.01m .. 0.99m
c is more or less immaterial. 1 or a is suggested.
-
+
NB: LOW ORDER BITS are not very random. To get small random numbers,
- treat result as <1, with implied binary point, and multiply by
+ treat result as <1, with implied binary point, and multiply by
desired modulus.
NB: Has to be unsigned, since shifts on signed quantities may preserve
the sign bit.
*/
-/* added rxi_getaddr() to try to get as much initial randomness as
- possible, since at least one customer reboots ALL their clients
+/* added rxi_getaddr() to try to get as much initial randomness as
+ possible, since at least one customer reboots ALL their clients
simultaneously -- so osi_Time is bound to be the same on some of the
clients. This is probably OK, but I don't want to see too much of it.
*/
afs_random(void)
{
static afs_int32 state = 0;
- register int i;
+ int i;
AFS_STATCNT(afs_random);
if (!state) {
/* returns int 0..14 using the high bits of a pseudo-random number instead of
the low bits, as the low bits are "less random" than the high ones...
slight roundoff error exists, an excercise for the reader.
- need to multiply by something with lots of ones in it, so multiply by
+ need to multiply by something with lots of ones in it, so multiply by
8 or 16 is right out.
*/
int
} /*afs_SortServers */
/* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
- data structures to determine what the local IP addresses and subnet masks
+ data structures to determine what the local IP addresses and subnet masks
are in order to choose which server(s) are on the local subnet.
As I see it, there are several cases:
4. The server is on a different logical subnet or net than this host, but
this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
one physical medium.
- 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
+ 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
server.
6. This host and the server are disjoint.
That is a rough order of preference. If a point-to-point link has a high
- metric, I'm assuming that it is a very slow link, and putting it at the
- bottom of the list (at least until RX works better over slow links). If
- its metric is 1, I'm assuming that it's relatively fast (T1) and putting
+ metric, I'm assuming that it is a very slow link, and putting it at the
+ bottom of the list (at least until RX works better over slow links). If
+ its metric is 1, I'm assuming that it's relatively fast (T1) and putting
it ahead of #6.
It's not easy to check for case #4, so I'm ignoring it for the time being.
BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
- That could be used to prefer certain servers fairly easily. Maybe some
+ That could be used to prefer certain servers fairly easily. Maybe some
other time...
NOTE: this code is very system-dependent, and very dependent on the TCP/IP
/*
* The IP addresses and ranks are determined by afsd (in user space) and
* passed into the kernel at startup time through the AFSOP_ADVISEADDR
- * system call. These are stored in the data structure
- * called 'afs_cb_interface'.
+ * system call. These are stored in the data structure
+ * called 'afs_cb_interface'.
*
* struct srvAddr *sa; remote server
* afs_int32 addr; one of my local addr in net order
return;
}
#else /* AFS_USERSPACE_IP_ADDR */
-#if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
+#if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
void
afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
{
#endif /* IFF_POINTTOPOINT */
}
#endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
+#if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
#ifndef afs_min
#define afs_min(A,B) ((A)<(B)) ? (A) : (B)
#endif
void
-afsi_SetServerIPRank(sa, ifa)
- struct srvAddr *sa;
-#ifdef AFS_DARWIN80_ENV
- ifaddr_t ifa;
-#else
- struct ifaddr *ifa;
-#endif
+afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
{
struct sockaddr sout;
struct sockaddr_in *sin;
afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
afs_uint32 serverAddr;
- if (ifaddr_address_family(ifa) != AF_INET)
+ if (rx_ifaddr_address_family(ifa) != AF_INET)
return;
- t = ifaddr_address(ifa, &sout, sizeof(sout));
- if (t == 0) {
+ t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
+ if (t != 0) {
sin = (struct sockaddr_in *)&sout;
myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
} else {
myAddr = 0;
}
serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
- t = ifaddr_netmask(ifa, &sout, sizeof(sout));
- if (t == 0) {
+ t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
+ if (t != 0) {
sin = (struct sockaddr_in *)&sout;
subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
} else {
subnetmask = 0;
}
- t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
- if (t == 0) {
+ t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
+ if (t != 0) {
sin = (struct sockaddr_in *)&sout;
- myDstaddr = sin->sin_addr.s_addr;
+ myDstaddr = ntohl(sin->sin_addr.s_addr);
} else {
myDstaddr = 0;
}
if (serverAddr == myAddr) { /* same machine */
sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
} else { /* same subnet */
- sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
+ sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
}
} else { /* same net */
- sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
+ sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
}
}
#ifdef IFF_POINTTOPOINT
/* check for case #4 -- point-to-point link */
- if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
+ if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
&& (myDstaddr == serverAddr)) {
- if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
+ if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
t = MAXDEFRANK;
else
- t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
+ t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
if (sa->sa_iprank > t)
sa->sa_iprank = t;
}
#ifdef AFS_SGI62_ENV
static int
-
- afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
- caddr_t arg2) {
+afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
+ caddr_t arg2)
+{
afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
return 0; /* Never match, so we enumerate everyone */
}
#endif /* AFS_SGI62_ENV */
-static int afs_SetServerPrefs(struct srvAddr *sa) {
+static int
+afs_SetServerPrefs(struct srvAddr *sa)
+{
#if defined(AFS_USERSPACE_IP_ADDR)
int i;
#ifdef notdef
if (!s) {
- if (afsifinfo[i].ipaddr != 0x7f000001) { /* ignore loopback */
+ if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) { /* ignore loopback */
*cnt += 1;
if (*cnt > 16)
return;
}
}
}
-
+
rw_exit(&afsifinfo_lock);
#else
for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
subnetmask = ipif->ipif_net_mask;
/*
- * Generate the local net using the local address and
+ * Generate the local net using the local address and
* whate we know about Class A, B and C networks.
*/
if (IN_CLASSA(ipif->ipif_local_addr)) {
net = ipif->ipif_local_addr & netmask;
#ifdef notdef
if (!s) {
- if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
+ if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) { /* ignore loopback */
*cnt += 1;
if (*cnt > 16)
return;
#endif /* AFS_SUN510_ENV */
#else
#ifndef USEIFADDR
- struct ifnet *ifn = NULL;
+ rx_ifnet_t ifn = NULL;
struct in_ifaddr *ifad = (struct in_ifaddr *)0;
struct sockaddr_in *sin;
errno_t t;
unsigned int count;
int cnt=0, m, j;
- ifaddr_t *ifads;
- ifnet_t *ifn;
+ rx_ifaddr_t *ifads;
+ rx_ifnet_t *ifns;
- if (!ifnet_list_get(AF_INET, &ifn, &count)) {
+ if (!ifnet_list_get(AF_INET, &ifns, &count)) {
for (m = 0; m < count; m++) {
- if (!ifnet_get_address_list(ifn[m], &ifads)) {
+ if (!ifnet_get_address_list(ifns[m], &ifads)) {
for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
afsi_SetServerIPRank(sa, ifads[j]);
cnt++;
ifnet_free_address_list(ifads);
}
}
- ifnet_list_free(ifn);
+ ifnet_list_free(ifns);
}
}
-#elif defined(AFS_DARWIN60_ENV)
+#elif defined(AFS_DARWIN_ENV)
{
- struct ifnet *ifn;
- struct ifaddr *ifa;
+ rx_ifnet_t ifn;
+ rx_ifaddr_t ifa;
TAILQ_FOREACH(ifn, &ifnet, if_link) {
TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
afsi_SetServerIPRank(sa, ifa);
}}}
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#elif defined(AFS_FBSD_ENV)
{
struct in_ifaddr *ifa;
TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
afsi_SetServerIPRank(sa, ifa);
}
+#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
{
struct in_ifaddr *ifa;
afsi_SetServerIPRank(sa, ifa);
}}
#endif
- end:
#endif /* USEIFADDR */
+#ifndef USEIFADDR
+ end:
+#endif
#endif /* AFS_SUN5_ENV */
#endif /* else AFS_USERSPACE_IP_ADDR */
if (sa)
* clean up all other structures that may reference it.
* The afs_xserver and afs_xsrvAddr locks are assumed taken.
*/
-void afs_FlushServer(struct server *srvp) {
+void
+afs_FlushServer(struct server *srvp)
+{
afs_int32 i;
struct server *ts, **pts;
if (srvp->cbrs) {
struct afs_cbr *cb, *cbnext;
- MObtainWriteLock(&afs_xvcb, 300);
+ ObtainWriteLock(&afs_xvcb, 300);
for (cb = srvp->cbrs; cb; cb = cbnext) {
cbnext = cb->next;
afs_FreeCBR(cb);
* The afs_xserver and afs_xsrvAddr locks are assumed taken.
* It is not removed from the afs_srvAddrs hash chain.
*/
-void afs_RemoveSrvAddr(struct srvAddr *sap) {
+void
+afs_RemoveSrvAddr(struct srvAddr *sap)
+{
struct srvAddr **psa, *sa;
struct server *srv;
}
}
+/* afs_GetCapabilities
+ * Try and retrieve capabilities of a given file server. Carps on actual
+ * failure. Servers are not expected to support this RPC. */
+void
+afs_GetCapabilities(struct server *ts)
+{
+ Capabilities caps = {0, NULL};
+ struct vrequest treq;
+ struct afs_conn *tc;
+ struct unixuser *tu;
+ struct rx_connection *rxconn;
+ afs_int32 code;
+
+ if ( !ts || !ts->cell )
+ return;
+ if ( !afs_osi_credp )
+ return;
+
+ if ((code = afs_InitReq(&treq, afs_osi_credp)))
+ return;
+ tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
+ if ( !tu )
+ return;
+ tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
+ 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(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, 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! */
+ return;
+ }
+
+ ts->flags |= SCAPS_KNOWN;
+
+ if ( caps.Capabilities_len > 0 ) {
+ ts->capabilities = caps.Capabilities_val[0];
+ xdr_free((xdrproc_t)xdr_Capabilities, &caps);
+ caps.Capabilities_len = 0;
+ caps.Capabilities_val = NULL;
+ }
+
+}
+
/* afs_GetServer()
* Return an updated and properly initialized server structure
* corresponding to the server ID, cell, and port specified.
* If one does not exist, then one will be created.
* aserver and aport must be in NET byte order.
*/
-struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
- afs_int32 acell, u_short aport,
- afs_int32 locktype, afsUUID * uuidp,
- afs_int32 addr_uniquifier) {
+struct server *
+afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
+ u_short aport, afs_int32 locktype, afsUUID * uuidp,
+ afs_int32 addr_uniquifier)
+{
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 (oldts) {
newts = oldts;
} else {
- newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
+ newts = afs_osi_Alloc(sizeof(struct server));
if (!newts)
panic("malloc of server struct");
afs_totalServers++;
- memset((char *)newts, 0, sizeof(struct server));
+ memset(newts, 0, sizeof(struct server));
/* Add the server struct to the afs_servers[] hash chain */
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]);
if (oldsa) {
newsa = oldsa;
} else {
- newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
+ newsa = afs_osi_Alloc(sizeof(struct srvAddr));
if (!newsa)
panic("malloc of srvAddr struct");
afs_totalSrvAddrs++;
- memset((char *)newsa, 0, sizeof(struct srvAddr));
+ memset(newsa, 0, sizeof(struct srvAddr));
/* Add the new srvAddr to the afs_srvAddrs[] hash chain */
newsa->next_bkt = afs_srvAddrs[iphash];
/* Have a srvAddr struct. Now get a server struct (if not already) */
if (!orphts) {
- orphts =
- (struct server *)afs_osi_Alloc(sizeof(struct server));
+ orphts = afs_osi_Alloc(sizeof(struct server));
if (!orphts)
panic("malloc of lo server struct");
- memset((char *)orphts, 0, sizeof(struct server));
+ memset(orphts, 0, sizeof(struct server));
afs_totalServers++;
/* Add the orphaned server to the afs_servers[] hash chain.
* Its iphash does not matter since we never look up the server
- * in the afs_servers table by its ip address (only by uuid -
+ * in the afs_servers table by its ip address (only by uuid -
* which this has none).
*/
iphash = SHash(aserverp[k]);
}
ReleaseWriteLock(&afs_xsrvAddr);
+
+ if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
+ afs_GetCapabilities(newts);
+
ReleaseWriteLock(&afs_xserver);
return (newts);
} /* afs_GetServer */
-void afs_ActivateServer(struct srvAddr *sap) {
+void
+afs_ActivateServer(struct srvAddr *sap)
+{
osi_timeval_t currTime; /*Filled with current time */
osi_timeval_t *currTimeP; /*Ptr to above */
struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
}
}
-void afs_RemoveAllConns(void)
+void
+afs_RemoveAllConns(void)
{
int i;
struct server *ts, *nts;
struct srvAddr *sa;
- struct afs_conn *tc, *ntc;
ObtainReadLock(&afs_xserver);
ObtainWriteLock(&afs_xconn, 1001);
-
+
/*printf("Destroying connections ... ");*/
for (i = 0; i < NSERVERS; i++) {
for (ts = afs_servers[i]; ts; ts = nts) {
nts = ts->next;
for (sa = ts->addr; sa; sa = sa->next_sa) {
if (sa->conns) {
- tc = sa->conns;
- while (tc) {
- ntc = tc->next;
- AFS_GUNLOCK();
- rx_DestroyConnection(tc->id);
- AFS_GLOCK();
- afs_osi_Free(tc, sizeof(struct afs_conn));
- tc = ntc;
- }
+ afs_ReleaseConns(sa->conns);
sa->conns = NULL;
}
}
ReleaseWriteLock(&afs_xconn);
ReleaseReadLock(&afs_xserver);
-
+
}
-void afs_MarkAllServersUp(void)
+void
+afs_MarkAllServersUp(void)
{
int i;
struct server *ts;
ReleaseWriteLock(&afs_xsrvAddr);
ReleaseWriteLock(&afs_xserver);
}
-
-void shutdown_server(void)
-{
- int i;
-
- for (i = 0; i < NSERVERS; i++) {
- struct server *ts, *next;
-
- ts = afs_servers[i];
- while(ts) {
- next = ts->next;
- afs_osi_Free(ts, sizeof(struct server));
- ts = next;
- }
- }
-
- for (i = 0; i < NSERVERS; i++) {
- struct srvAddr *sa, *next;
-
- sa = afs_srvAddrs[i];
- while(sa) {
- next = sa->next_bkt;
- afs_osi_Free(sa, sizeof(struct srvAddr));
- sa = next;
- }
- }
-}