2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
12 * afs_MarkServerUpOrDown
20 * afsi_SetServerIPRank
32 #include <afsconfig.h>
33 #include "afs/param.h"
37 #include "afs/sysincludes.h" /* Standard vendor system headers */
40 #if !defined(AFS_LINUX20_ENV)
43 #include <netinet/in.h>
46 #include "h/hashing.h"
48 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
49 #include <netinet/in_var.h>
50 #endif /* AFS_HPUX110_ENV */
52 #include <net/if_var.h>
54 #endif /* !defined(UKERNEL) */
56 #include "afsincludes.h" /* Afs-based standard headers */
57 #include "afs/afs_stats.h" /* afs statistics */
58 #include "rx/rx_multi.h"
60 #if defined(AFS_SUN5_ENV)
62 #include <inet/common.h>
63 #include <netinet/ip6.h>
64 #define ipif_local_addr ipif_lcl_addr
66 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
71 /* Exported variables */
72 afs_rwlock_t afs_xserver; /* allocation lock for servers */
73 struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
74 afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
75 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
78 /* debugging aids - number of alloc'd server and srvAddr structs. */
79 int afs_reuseServers = 0;
80 int afs_reuseSrvAddrs = 0;
81 int afs_totalServers = 0;
82 int afs_totalSrvAddrs = 0;
86 static struct afs_stats_SrvUpDownInfo *
87 GetUpDownStats(struct server *srv)
89 struct afs_stats_SrvUpDownInfo *upDownP;
90 u_short fsport = AFS_FSPORT;
93 fsport = srv->cell->fsport;
95 if (srv->addr->sa_portal == fsport)
96 upDownP = afs_stats_cmperf.fs_UpDown;
98 upDownP = afs_stats_cmperf.vl_UpDown;
100 if (srv->cell && afs_IsPrimaryCell(srv->cell))
101 return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
103 return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
107 /*------------------------------------------------------------------------
108 * afs_MarkServerUpOrDown
111 * Mark the given server up or down, and track its uptime stats.
114 * a_serverP : Ptr to server record to fiddle with.
115 * a_isDown : Is the server is to be marked down?
121 * The CM server structures must be write-locked.
125 *------------------------------------------------------------------------*/
128 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
130 struct server *a_serverP = sa->server;
132 osi_timeval_t currTime, *currTimeP; /*Current time */
133 afs_int32 downTime; /*Computed downtime, in seconds */
134 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
137 * If the server record is marked the same as the new status we've
138 * been fed, then there isn't much to be done.
140 if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
141 || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
145 sa->sa_flags |= SRVADDR_ISDOWN;
146 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
147 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
148 /* Not all ips are up so don't bother with the
149 * server's up/down stats */
154 * All ips are down we treat the whole server down
156 a_serverP->flags |= SRVR_ISDOWN;
158 sa->sa_flags &= ~SRVADDR_ISDOWN;
159 /* If any ips are up, the server is also marked up */
160 a_serverP->flags &= ~SRVR_ISDOWN;
161 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
162 if (sap->sa_flags & SRVADDR_ISDOWN) {
163 /* Not all ips are up so don't bother with the
164 * server's up/down stats */
171 * Compute the current time and which overall stats record is to be
172 * updated; we'll need them one way or another.
174 currTimeP = &currTime;
175 osi_GetuTime(currTimeP);
177 upDownP = GetUpDownStats(a_serverP);
181 * Server going up -> down; remember the beginning of this
184 a_serverP->lastDowntimeStart = currTime.tv_sec;
186 (upDownP->numDownRecords)++;
187 (upDownP->numUpRecords)--;
188 } /*Server being marked down */
191 * Server going down -> up; remember everything about this
192 * newly-completed downtime incident.
194 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
195 (a_serverP->numDowntimeIncidents)++;
196 a_serverP->sumOfDowntimes += downTime;
198 (upDownP->numUpRecords)++;
199 (upDownP->numDownRecords)--;
200 (upDownP->numDowntimeIncidents)++;
201 if (a_serverP->numDowntimeIncidents == 1)
202 (upDownP->numRecordsNeverDown)--;
203 upDownP->sumOfDowntimes += downTime;
204 if ((upDownP->shortestDowntime == 0)
205 || (downTime < upDownP->shortestDowntime))
206 upDownP->shortestDowntime = downTime;
207 if ((upDownP->longestDowntime == 0)
208 || (downTime > upDownP->longestDowntime))
209 upDownP->longestDowntime = downTime;
212 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
213 (upDownP->downDurations[0])++;
214 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
215 (upDownP->downDurations[1])++;
216 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
217 (upDownP->downDurations[2])++;
218 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
219 (upDownP->downDurations[3])++;
220 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
221 (upDownP->downDurations[4])++;
222 else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
223 (upDownP->downDurations[5])++;
225 (upDownP->downDurations[6])++;
227 } /*Server being marked up */
229 } /*MarkServerUpOrDown */
233 afs_ServerDown(struct srvAddr *sa)
235 struct server *aserver = sa->server;
237 AFS_STATCNT(ServerDown);
238 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
240 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
241 if (sa->sa_portal == aserver->cell->vlport)
242 print_internet_address
243 ("afs: Lost contact with volume location server ", sa, "", 1);
245 print_internet_address("afs: Lost contact with file server ", sa, "",
251 /* return true if we have any callback promises from this server */
253 afs_HaveCallBacksFrom(struct server *aserver)
259 AFS_STATCNT(HaveCallBacksFrom);
260 now = osi_Time(); /* for checking for expired callbacks */
261 for (i = 0; i < VCSIZE; i++) { /* for all guys in the hash table */
262 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
264 * Check to see if this entry has an unexpired callback promise
265 * from the required host
267 if (aserver == tvc->callback && tvc->cbExpires >= now
268 && ((tvc->f.states & CRO) == 0))
274 } /*HaveCallBacksFrom */
278 CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
280 struct server *aserver = sa->server;
283 struct rx_connection *rxconn;
285 AFS_STATCNT(CheckVLServer);
286 /* Ping dead servers to see if they're back */
287 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
288 || (aserver->flags & SRVR_ISGONE))
291 return; /* can't do much */
293 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
294 aserver->cell->cellNum, areq, 1, SHARED_LOCK, &rxconn);
297 rx_SetConnDeadTime(rxconn, 3);
300 code = VL_ProbeServer(rxconn);
302 rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
303 afs_PutConn(tc, rxconn, SHARED_LOCK);
305 * If probe worked, or probe call not yet defined (for compatibility
306 * with old vlsevers), then we treat this server as running again
308 if (code == 0 || (code <= -450 && code >= -470)) {
309 if (tc->parent->srvr == sa) {
310 afs_MarkServerUpOrDown(sa, 0);
311 print_internet_address("afs: volume location server ", sa,
319 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
320 #define AFS_MINCHANGE 2 /* min change we'll bother with */
322 #ifndef AFS_MAXCHANGEBACK
323 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
327 /*------------------------------------------------------------------------
328 * EXPORTED afs_CountServers
331 * Originally meant to count the number of servers and determining
332 * up/down info, this routine will now simply sum up all of the
333 * server record ages. All other up/down information is kept on the
343 * This routine locks afs_xserver for write for the duration.
346 * Set CM perf stats field sumOfRecordAges for all server record
348 *------------------------------------------------------------------------*/
351 afs_CountServers(void)
353 int currIdx; /*Curr idx into srv table */
354 struct server *currSrvP; /*Ptr to curr server record */
355 afs_int32 currChainLen; /*Length of curr hash chain */
356 osi_timeval_t currTime; /*Current time */
357 osi_timeval_t *currTimeP; /*Ptr to above */
358 afs_int32 srvRecordAge; /*Age of server record, in secs */
359 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
360 * info being manipulated */
363 * Write-lock the server table so we don't get any interference.
365 ObtainReadLock(&afs_xserver);
368 * Iterate over each hash index in the server table, walking down each
369 * chain and tallying what we haven't computed from the records there on
370 * the fly. First, though, initialize the tallies that will change.
372 afs_stats_cmperf.srvMaxChainLength = 0;
374 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
375 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
376 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
377 memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
378 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
380 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
381 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
382 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
383 memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
384 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
386 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
387 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
388 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
389 memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
390 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
392 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
393 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
394 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
395 memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
396 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
399 * Compute the current time, used to figure out server record ages.
401 currTimeP = &currTime;
402 osi_GetuTime(currTimeP);
405 * Sweep the server hash table, tallying all we need to know.
407 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
409 for (currSrvP = afs_servers[currIdx]; currSrvP;
410 currSrvP = currSrvP->next) {
412 * Bump the current chain length.
417 * Any further tallying for this record will only be done if it has
420 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
421 && currSrvP->addr && currSrvP->cell) {
424 * Compute the current server record's age, then remember it
425 * in the appropriate places.
427 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
428 upDownP = GetUpDownStats(currSrvP);
429 upDownP->sumOfRecordAges += srvRecordAge;
430 if ((upDownP->ageOfYoungestRecord == 0)
431 || (srvRecordAge < upDownP->ageOfYoungestRecord))
432 upDownP->ageOfYoungestRecord = srvRecordAge;
433 if ((upDownP->ageOfOldestRecord == 0)
434 || (srvRecordAge > upDownP->ageOfOldestRecord))
435 upDownP->ageOfOldestRecord = srvRecordAge;
437 if (currSrvP->numDowntimeIncidents <=
438 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
439 (upDownP->downIncidents[0])++;
440 else if (currSrvP->numDowntimeIncidents <=
441 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
442 (upDownP->downIncidents[1])++;
443 else if (currSrvP->numDowntimeIncidents <=
444 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
445 (upDownP->downIncidents[2])++;
446 else if (currSrvP->numDowntimeIncidents <=
447 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
448 (upDownP->downIncidents[3])++;
449 else if (currSrvP->numDowntimeIncidents <=
450 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
451 (upDownP->downIncidents[4])++;
453 (upDownP->downIncidents[5])++;
456 } /*Current server has been active */
457 } /*Walk this chain */
460 * Before advancing to the next chain, remember facts about this one.
462 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
464 * We beat out the former champion (which was initially set to 0
465 * here). Mark down the new winner, and also remember if it's an
468 afs_stats_cmperf.srvMaxChainLength = currChainLen;
469 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
470 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
471 } /*Update chain length maximum */
472 } /*For each hash chain */
475 * We're done. Unlock the server table before returning to our caller.
477 ReleaseReadLock(&afs_xserver);
479 } /*afs_CountServers */
483 ForceAllNewConnections(void)
486 struct srvAddr **addrs;
490 ObtainReadLock(&afs_xserver); /* Necessary? */
491 ObtainReadLock(&afs_xsrvAddr);
494 for (i = 0; i < NSERVERS; i++) {
495 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
500 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
501 osi_Assert(addrs != NULL);
503 for (i = 0; i < NSERVERS; i++) {
504 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
505 if (j >= srvAddrCount)
511 ReleaseReadLock(&afs_xsrvAddr);
512 ReleaseReadLock(&afs_xserver);
513 for (i = 0; i < j; i++) {
515 ForceNewConnections(sa);
520 CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
526 for(i = 0; i < nconns; i++){
528 sa = tc->parent->srvr;
530 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
531 (tc->parent->srvr == sa)) {
533 print_internet_address("afs: file server ", sa, " is back up", 2);
535 ObtainWriteLock(&afs_xserver, 244);
536 ObtainWriteLock(&afs_xsrvAddr, 245);
537 afs_MarkServerUpOrDown(sa, 0);
538 ReleaseWriteLock(&afs_xsrvAddr);
539 ReleaseWriteLock(&afs_xserver);
541 if (afs_waitForeverCount) {
542 afs_osi_Wakeup(&afs_waitForever);
545 if (results[i] < 0) {
548 ForceNewConnections(sa); /* multi homed clients */
555 CkSrv_GetCaps(struct rx_connection **rxconns, int nconns, int nservers,
556 struct afs_conn **conns, struct srvAddr **addrs)
563 caps = afs_osi_Alloc(nservers * sizeof (Capabilities));
564 osi_Assert(caps != NULL);
565 memset(caps, 0, nservers * sizeof(Capabilities));
567 results = afs_osi_Alloc(nservers * sizeof (afs_int32));
568 osi_Assert(results != NULL);
571 multi_Rx(rxconns,nconns)
573 multi_RXAFS_GetCapabilities(&caps[multi_i]);
574 results[multi_i] = multi_error;
578 for ( i = 0 ; i < nconns ; i++ ) {
579 ts = addrs[i]->server;
582 ts->capabilities = 0;
583 ts->flags |= SCAPS_KNOWN;
584 if ( results[i] == RXGEN_OPCODE ) {
585 /* Mark server as up - it responded */
589 if ( results[i] >= 0 )
590 /* we currently handle 32-bits of capabilities */
591 if (caps[i].Capabilities_len > 0) {
592 ts->capabilities = caps[i].Capabilities_val[0];
593 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
594 caps[i].Capabilities_val = NULL;
595 caps[i].Capabilities_len = 0;
598 CkSrv_MarkUpDown(conns, nconns, results);
600 afs_osi_Free(caps, nservers * sizeof(Capabilities));
601 afs_osi_Free(results, nservers * sizeof(afs_int32));
604 /* check down servers (if adown), or running servers (if !adown) */
606 afs_CheckServers(int adown, struct cell *acellp)
608 afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
611 /* adown: AFS_LS_UP - check only up
612 * AFS_LS_DOWN - check only down.
613 * AFS_LS_ALL - check all */
615 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
616 void (*func1) (struct rx_connection **rxconns, int nconns,
617 int nservers, struct afs_conn **conns,
618 struct srvAddr **addrs),
619 void (*func2) (struct rx_connection **rxconns, int nconns,
620 int nservers, struct afs_conn **conns,
621 struct srvAddr **addrs))
623 struct vrequest treq;
626 struct afs_conn *tc = NULL;
631 struct srvAddr **addrs;
632 struct afs_conn **conns;
634 struct rx_connection **rxconns;
635 afs_int32 *conntimer, *results;
637 AFS_STATCNT(afs_CheckServers);
640 * No sense in doing the server checks if we are running in disconnected
643 if (AFS_IS_DISCONNECTED)
646 conns = (struct afs_conn **)0;
647 rxconns = (struct rx_connection **) 0;
651 if ((code = afs_InitReq(&treq, afs_osi_credp)))
653 ObtainReadLock(&afs_xserver); /* Necessary? */
654 ObtainReadLock(&afs_xsrvAddr);
657 for (i = 0; i < NSERVERS; i++) {
658 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
663 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
664 osi_Assert(addrs != NULL);
666 for (i = 0; i < NSERVERS; i++) {
667 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
668 if (j >= srvAddrCount)
674 ReleaseReadLock(&afs_xsrvAddr);
675 ReleaseReadLock(&afs_xserver);
677 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
678 osi_Assert(conns != NULL);
679 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
680 osi_Assert(rxconns != NULL);
681 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
682 osi_Assert(conntimer != NULL);
683 results = afs_osi_Alloc(j * sizeof (afs_int32));
684 osi_Assert(results != NULL);
686 for (i = 0; i < j; i++) {
687 struct rx_connection *rxconn;
693 /* See if a cell to check was specified. If it is spec'd and not
694 * this server's cell, just skip the server.
696 if (acellp && acellp != ts->cell)
699 if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
700 || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
703 /* check vlserver with special code */
704 if (sa->sa_portal == AFS_VLPORT) {
706 CheckVLServer(sa, &treq);
710 if (!ts->cell) /* not really an active server, anyway, it must */
711 continue; /* have just been added by setsprefs */
713 /* get a connection, even if host is down; bumps conn ref count */
714 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
715 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
716 1 /*force */ , 1 /*create */ , SHARED_LOCK, &rxconn);
717 afs_PutUser(tu, SHARED_LOCK);
721 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
723 rxconns[nconns]=rxconn;
724 if (sa->sa_flags & SRVADDR_ISDOWN) {
725 rx_SetConnDeadTime(rxconn, 3);
732 } /* Outer loop over addrs */
734 (*func1)(rxconns, nconns, j, conns, addrs);
737 (*func2)(rxconns, nconns, j, conns, addrs);
740 for (i = 0; i < nconns; i++) {
741 if (conntimer[i] == 1)
742 rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
743 afs_PutConn(conns[i], rxconns[i], SHARED_LOCK); /* done with it now */
746 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
747 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
748 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
749 afs_osi_Free(conntimer, j * sizeof(afs_int32));
750 afs_osi_Free(results, j * sizeof(afs_int32));
752 } /*afs_CheckServers*/
755 /* find a server structure given the host address */
757 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
764 AFS_STATCNT(afs_FindServer);
766 i = afs_uuid_hash(uuidp) % NSERVERS;
767 for (ts = afs_servers[i]; ts; ts = ts->next) {
768 if ((ts->flags & SRVR_MULTIHOMED)
770 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
771 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
776 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
777 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
784 } /*afs_FindServer */
787 /* some code for creating new server structs and setting preferences follows
788 * in the next few lines...
791 #define MAXDEFRANK 60000
792 #define DEFRANK 40000
794 /* Random number generator and constants from KnuthV2 2d ed, p170 */
800 a is 0.73m should be 0.01m .. 0.99m
801 c is more or less immaterial. 1 or a is suggested.
803 NB: LOW ORDER BITS are not very random. To get small random numbers,
804 treat result as <1, with implied binary point, and multiply by
806 NB: Has to be unsigned, since shifts on signed quantities may preserve
809 /* added rxi_getaddr() to try to get as much initial randomness as
810 possible, since at least one customer reboots ALL their clients
811 simultaneously -- so osi_Time is bound to be the same on some of the
812 clients. This is probably OK, but I don't want to see too much of it.
815 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
820 static afs_int32 state = 0;
823 AFS_STATCNT(afs_random);
828 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
829 * bits are in a tv_usec
831 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
832 state += (t.tv_sec & 0xff);
833 for (i = 0; i < 30; i++) {
843 /* returns int 0..14 using the high bits of a pseudo-random number instead of
844 the low bits, as the low bits are "less random" than the high ones...
845 slight roundoff error exists, an excercise for the reader.
846 need to multiply by something with lots of ones in it, so multiply by
847 8 or 16 is right out.
850 afs_randomMod15(void)
854 temp = afs_random() >> 4;
855 temp = (temp * 15) >> 28;
861 afs_randomMod127(void)
865 temp = afs_random() >> 7;
866 temp = (temp * 127) >> 25;
871 /* afs_SortOneServer()
872 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
875 afs_SortOneServer(struct server *asp)
877 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
880 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
882 lowsa = *rootsa; /* lowest sa is the first one */
883 lowrank = lowsa->sa_iprank;
885 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
886 rank = tsa->next_sa->sa_iprank;
887 if (rank < lowrank) {
889 lowsa = tsa->next_sa;
890 lowrank = lowsa->sa_iprank;
893 if (lowprev) { /* found one lower, so rearrange them */
894 lowprev->next_sa = lowsa->next_sa;
895 lowsa->next_sa = *rootsa;
902 * Sort the pointer to servers by the server's rank (its lowest rank).
903 * It is assumed that the server already has its IP addrs sorted (the
904 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
907 afs_SortServers(struct server *aservers[], int count)
912 AFS_STATCNT(afs_SortServers);
914 for (i = 0; i < count; i++) {
917 for (low = i, j = i + 1; j <= count; j++) {
918 if ((!aservers[j]) || (!aservers[j]->addr))
920 if ((!aservers[low]) || (!aservers[low]->addr))
922 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
928 aservers[i] = aservers[low];
932 } /*afs_SortServers */
934 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
935 data structures to determine what the local IP addresses and subnet masks
936 are in order to choose which server(s) are on the local subnet.
938 As I see it, there are several cases:
939 1. The server address is one of this host's local addresses. In this case
940 this server is to be preferred over all others.
941 2. The server is on the same subnet as one of the this host's local
942 addresses. (ie, an odd-sized subnet, not class A,B,orC)
943 3. The server is on the same net as this host (class A,B or C)
944 4. The server is on a different logical subnet or net than this host, but
945 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
947 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
949 6. This host and the server are disjoint.
951 That is a rough order of preference. If a point-to-point link has a high
952 metric, I'm assuming that it is a very slow link, and putting it at the
953 bottom of the list (at least until RX works better over slow links). If
954 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
956 It's not easy to check for case #4, so I'm ignoring it for the time being.
958 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
959 That could be used to prefer certain servers fairly easily. Maybe some
962 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
963 protocols (well, addresses that are stored in uint32s, at any rate).
966 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
967 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
969 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
970 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
975 #define PPWEIGHT 4096
979 #ifdef AFS_USERSPACE_IP_ADDR
981 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
984 * The IP addresses and ranks are determined by afsd (in user space) and
985 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
986 * system call. These are stored in the data structure
987 * called 'afs_cb_interface'.
989 * struct srvAddr *sa; remote server
990 * afs_int32 addr; one of my local addr in net order
991 * afs_uint32 subnetmask; subnet mask of local addr in net order
995 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
996 afs_uint32 subnetmask)
998 afs_uint32 myAddr, myNet, mySubnet, netMask;
999 afs_uint32 serverAddr;
1001 myAddr = ntohl(addr); /* one of my IP addr in host order */
1002 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1003 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1005 if (IN_CLASSA(myAddr))
1006 netMask = IN_CLASSA_NET;
1007 else if (IN_CLASSB(myAddr))
1008 netMask = IN_CLASSB_NET;
1009 else if (IN_CLASSC(myAddr))
1010 netMask = IN_CLASSC_NET;
1014 myNet = myAddr & netMask;
1015 mySubnet = myAddr & subnetmask;
1017 if ((serverAddr & netMask) == myNet) {
1018 if ((serverAddr & subnetmask) == mySubnet) {
1019 if (serverAddr == myAddr) { /* same machine */
1020 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1021 } else { /* same subnet */
1022 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1024 } else { /* same net */
1025 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1030 #else /* AFS_USERSPACE_IP_ADDR */
1031 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1033 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1035 struct sockaddr_in *sin;
1038 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1039 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1041 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1042 sa->sa_iprank = TOPR;
1044 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1045 if (sa->sa_iprank > t)
1049 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1050 if (sa->sa_iprank > t)
1054 #ifdef IFF_POINTTOPOINT
1055 /* check for case #4 -- point-to-point link */
1056 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1057 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1058 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1061 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1062 if (sa->sa_iprank > t)
1065 #endif /* IFF_POINTTOPOINT */
1067 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1068 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV)) && defined(USEIFADDR)
1070 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1073 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1075 struct sockaddr sout;
1076 struct sockaddr_in *sin;
1079 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1080 afs_uint32 serverAddr;
1082 if (rx_ifaddr_address_family(ifa) != AF_INET)
1084 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1086 sin = (struct sockaddr_in *)&sout;
1087 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1091 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1092 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1094 sin = (struct sockaddr_in *)&sout;
1095 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1099 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1101 sin = (struct sockaddr_in *)&sout;
1102 myDstaddr = ntohl(sin->sin_addr.s_addr);
1107 if (IN_CLASSA(myAddr))
1108 netMask = IN_CLASSA_NET;
1109 else if (IN_CLASSB(myAddr))
1110 netMask = IN_CLASSB_NET;
1111 else if (IN_CLASSC(myAddr))
1112 netMask = IN_CLASSC_NET;
1116 myNet = myAddr & netMask;
1117 mySubnet = myAddr & subnetmask;
1119 if ((serverAddr & netMask) == myNet) {
1120 if ((serverAddr & subnetmask) == mySubnet) {
1121 if (serverAddr == myAddr) { /* same machine */
1122 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1123 } else { /* same subnet */
1124 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1126 } else { /* same net */
1127 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1130 #ifdef IFF_POINTTOPOINT
1131 /* check for case #4 -- point-to-point link */
1132 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1133 && (myDstaddr == serverAddr)) {
1134 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1137 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1138 if (sa->sa_iprank > t)
1141 #endif /* IFF_POINTTOPOINT */
1143 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1144 #endif /* else AFS_USERSPACE_IP_ADDR */
1146 #ifdef AFS_SGI62_ENV
1148 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1151 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1152 return 0; /* Never match, so we enumerate everyone */
1154 #endif /* AFS_SGI62_ENV */
1156 afs_SetServerPrefs(struct srvAddr *sa)
1158 #if defined(AFS_USERSPACE_IP_ADDR)
1162 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1163 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1164 afs_cb_interface.subnetmask[i]);
1166 #else /* AFS_USERSPACE_IP_ADDR */
1167 #if defined(AFS_SUN5_ENV)
1168 #ifdef AFS_SUN510_ENV
1171 extern struct ill_s *ill_g_headp;
1172 long *addr = (long *)ill_g_headp;
1176 int subnet, subnetmask, net, netmask;
1180 #ifdef AFS_SUN510_ENV
1181 rw_enter(&afsifinfo_lock, RW_READER);
1183 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1185 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1186 netmask = IN_CLASSA_NET;
1187 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1188 netmask = IN_CLASSB_NET;
1189 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1190 netmask = IN_CLASSC_NET;
1194 net = afsifinfo[i].ipaddr & netmask;
1198 if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) { /* ignore loopback */
1202 *addrp++ = afsifinfo[i].ipaddr;
1207 /* XXXXXX Do the individual ip ranking below XXXXX */
1208 if ((sa->sa_ip & netmask) == net) {
1209 if ((sa->sa_ip & subnetmask) == subnet) {
1210 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1211 sa->sa_iprank = TOPR;
1213 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1216 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1219 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1221 /* check for case #5 -- point-to-point link */
1222 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1223 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1225 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1226 sa->sa_iprank = MAXDEFRANK;
1228 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1233 rw_exit(&afsifinfo_lock);
1235 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1236 ill = ill->ill_next) {
1237 /* Make sure this is an IPv4 ILL */
1240 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1241 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1242 subnetmask = ipif->ipif_net_mask;
1244 * Generate the local net using the local address and
1245 * whate we know about Class A, B and C networks.
1247 if (IN_CLASSA(ipif->ipif_local_addr)) {
1248 netmask = IN_CLASSA_NET;
1249 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1250 netmask = IN_CLASSB_NET;
1251 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1252 netmask = IN_CLASSC_NET;
1256 net = ipif->ipif_local_addr & netmask;
1259 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) { /* ignore loopback */
1263 *addrp++ = ipif->ipif_local_addr;
1268 /* XXXXXX Do the individual ip ranking below XXXXX */
1269 if ((sa->sa_ip & netmask) == net) {
1270 if ((sa->sa_ip & subnetmask) == subnet) {
1271 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1272 sa->sa_iprank = TOPR;
1274 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1277 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1280 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1282 /* check for case #5 -- point-to-point link */
1283 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1284 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1286 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1287 sa->sa_iprank = MAXDEFRANK;
1289 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1294 #endif /* AFS_SUN510_ENV */
1297 rx_ifnet_t ifn = NULL;
1298 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1299 struct sockaddr_in *sin;
1302 #ifdef notdef /* clean up, remove this */
1303 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1304 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1305 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1306 && !(ifn->if_flags & IFF_LOOPBACK)) {
1311 ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1320 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1322 if (ifn) { /* local, more or less */
1324 if (ifn->if_flags & IFF_LOOPBACK) {
1325 sa->sa_iprank = TOPR;
1328 #endif /* IFF_LOOPBACK */
1329 sin = (struct sockaddr_in *)IA_SIN(ifad);
1330 if (SA2ULONG(sin) == sa->sa_ip) {
1331 sa->sa_iprank = TOPR;
1334 #ifdef IFF_BROADCAST
1335 if (ifn->if_flags & IFF_BROADCAST) {
1336 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1341 #endif /* IFF_BROADCAST */
1342 #ifdef IFF_POINTOPOINT
1343 if (ifn->if_flags & IFF_POINTOPOINT) {
1344 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1345 if (ifn->if_metric > 4) {
1349 sa->sa_iprank = ifn->if_metric;
1352 #endif /* IFF_POINTOPOINT */
1353 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1355 #else /* USEIFADDR */
1359 #ifdef AFS_SGI62_ENV
1360 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1361 (caddr_t) sa, NULL);
1362 #elif defined(AFS_DARWIN80_ENV)
1370 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1371 for (m = 0; m < count; m++) {
1372 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1373 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1374 afsi_SetServerIPRank(sa, ifads[j]);
1377 ifnet_free_address_list(ifads);
1380 ifnet_list_free(ifns);
1383 #elif defined(AFS_DARWIN_ENV)
1387 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1388 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1389 afsi_SetServerIPRank(sa, ifa);
1391 #elif defined(AFS_FBSD_ENV)
1393 struct in_ifaddr *ifa;
1394 #if defined(AFS_FBSD80_ENV)
1395 TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
1397 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1399 afsi_SetServerIPRank(sa, ifa);
1401 #elif defined(AFS_OBSD_ENV)
1403 extern struct in_ifaddrhead in_ifaddr;
1404 struct in_ifaddr *ifa;
1405 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1406 afsi_SetServerIPRank(sa, ifa);
1408 #elif defined(AFS_NBSD40_ENV)
1410 extern struct in_ifaddrhead in_ifaddrhead;
1411 struct in_ifaddr *ifa;
1412 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1413 afsi_SetServerIPRank(sa, ifa);
1417 struct in_ifaddr *ifa;
1418 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1419 afsi_SetServerIPRank(sa, ifa);
1422 #endif /* USEIFADDR */
1426 #endif /* AFS_SUN5_ENV */
1427 #endif /* else AFS_USERSPACE_IP_ADDR */
1429 sa->sa_iprank += afs_randomMod15();
1432 } /* afs_SetServerPrefs */
1440 /* afs_FlushServer()
1441 * The addresses on this server struct has changed in some way and will
1442 * clean up all other structures that may reference it.
1443 * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
1446 afs_FlushServer(struct server *srvp, struct volume *tv)
1449 struct server *ts, **pts;
1451 /* Find any volumes residing on this server and flush their state */
1452 afs_ResetVolumes(srvp, tv);
1454 /* Flush all callbacks in the all vcaches for this specific server */
1455 afs_FlushServerCBs(srvp);
1457 /* Remove all the callbacks structs */
1459 struct afs_cbr *cb, *cbnext;
1461 for (cb = srvp->cbrs; cb; cb = cbnext) {
1464 } srvp->cbrs = (struct afs_cbr *)0;
1467 /* If no more srvAddr structs hanging off of this server struct,
1471 /* Remove the server structure from the cell list - if there */
1472 afs_RemoveCellEntry(srvp);
1474 /* Remove from the afs_servers hash chain */
1475 for (i = 0; i < NSERVERS; i++) {
1476 for (pts = &(afs_servers[i]), ts = *pts; ts;
1477 pts = &(ts->next), ts = *pts) {
1485 *pts = ts->next; /* Found it. Remove it */
1486 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1492 /* afs_RemoveSrvAddr()
1493 * This removes a SrvAddr structure from its server structure.
1494 * The srvAddr struct is not free'd because it connections may still
1495 * be open to it. It is up to the calling process to make sure it
1496 * remains connected to a server struct.
1497 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1498 * It is not removed from the afs_srvAddrs hash chain.
1499 * If resetting volumes, do not reset volume tv
1502 afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
1504 struct srvAddr **psa, *sa;
1511 /* Find the srvAddr in the server's list and remove it */
1512 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1520 /* Flush the server struct since it's IP address has changed */
1521 afs_FlushServer(srv, tv);
1525 /* afs_GetCapabilities
1526 * Try and retrieve capabilities of a given file server. Carps on actual
1527 * failure. Servers are not expected to support this RPC. */
1529 afs_GetCapabilities(struct server *ts)
1531 Capabilities caps = {0, NULL};
1532 struct vrequest treq;
1533 struct afs_conn *tc;
1534 struct unixuser *tu;
1535 struct rx_connection *rxconn;
1538 if ( !ts || !ts->cell )
1540 if ( !afs_osi_credp )
1543 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1545 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1548 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1551 afs_PutUser(tu, SHARED_LOCK);
1554 /* InitCallBackStateN, triggered by our RPC, may need this */
1555 ReleaseWriteLock(&afs_xserver);
1556 code = RXAFS_GetCapabilities(rxconn, &caps);
1557 ObtainWriteLock(&afs_xserver, 723);
1558 /* we forced a conn above; important we mark it down if needed */
1559 if ((code < 0) && (code != RXGEN_OPCODE)) {
1560 afs_ServerDown(tc->parent->srvr);
1561 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1563 afs_PutConn(tc, rxconn, SHARED_LOCK);
1564 if ( code && code != RXGEN_OPCODE ) {
1565 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1566 /* better not be anything to free. we failed! */
1570 ts->flags |= SCAPS_KNOWN;
1572 if ( caps.Capabilities_len > 0 ) {
1573 ts->capabilities = caps.Capabilities_val[0];
1574 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1575 caps.Capabilities_len = 0;
1576 caps.Capabilities_val = NULL;
1581 static struct server *
1582 afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
1583 struct server **oldts, afs_int32 addr_uniquifier)
1585 struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
1586 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1587 /* Found a server struct that is multihomed and same
1588 * uniqufier (same IP addrs). The above if statement is the
1589 * same as in InstallUVolumeEntry().
1594 *oldts = ts; /* Will reuse if same uuid */
1599 * Return an updated and properly initialized server structure.
1601 * Takes a server ID, cell, and port.
1602 * If server does not exist, then one will be created.
1603 * @param[in] aserverp
1604 * The server address in network byte order
1605 * @param[in] nservers
1606 * The number of IP addresses claimed by the server
1608 * The cell the server is in
1610 * The port for the server (fileserver or vlserver) in network byte order
1611 * @param[in] locktype
1612 * The type of lock to hold when iterating server hash (unused).
1614 * The uuid for servers supporting one.
1615 * @param[in] addr_uniquifier
1616 * The vldb-provider per-instantiated-server uniquifer counter.
1618 * A volume not to reset information for if the server addresses
1622 * A server structure matching the request.
1625 afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
1626 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1627 afs_int32 addr_uniquifier, struct volume *tv)
1629 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1630 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1631 afs_int32 iphash, k, srvcount = 0;
1632 unsigned int srvhash;
1634 AFS_STATCNT(afs_GetServer);
1636 ObtainSharedLock(&afs_xserver, 13);
1638 /* Check if the server struct exists and is up to date */
1641 panic("afs_GetServer: incorrect count of servers");
1642 ObtainReadLock(&afs_xsrvAddr);
1643 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1644 ReleaseReadLock(&afs_xsrvAddr);
1645 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1646 /* Found a server struct that is not multihomed and has the
1647 * IP address associated with it. A correct match.
1649 ReleaseSharedLock(&afs_xserver);
1654 panic("afs_GetServer: incorrect count of servers");
1656 ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
1658 ReleaseSharedLock(&afs_xserver);
1664 * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
1665 * Do a little dance and see if we can grab xvcb. If not, we
1666 * need to recheck that oldts is still right after a drop and reobtain.
1668 if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
1669 ReleaseSharedLock(&afs_xserver);
1670 ObtainWriteLock(&afs_xvcb, 299);
1671 ObtainWriteLock(&afs_xserver, 35);
1673 /* we don't know what changed while we didn't hold the lock */
1675 ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
1678 ReleaseWriteLock(&afs_xserver);
1679 ReleaseWriteLock(&afs_xvcb);
1683 UpgradeSToWLock(&afs_xserver, 36);
1685 ObtainWriteLock(&afs_xsrvAddr, 116);
1686 srvcount = afs_totalServers;
1688 /* Reuse/allocate a new server structure */
1692 newts = afs_osi_Alloc(sizeof(struct server));
1694 panic("malloc of server struct");
1696 memset(newts, 0, sizeof(struct server));
1698 /* Add the server struct to the afs_servers[] hash chain */
1700 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1701 newts->next = afs_servers[srvhash];
1702 afs_servers[srvhash] = newts;
1705 /* Initialize the server structure */
1706 if (uuidp) { /* Multihomed */
1707 newts->sr_uuid = *uuidp;
1708 newts->sr_addr_uniquifier = addr_uniquifier;
1709 newts->flags |= SRVR_MULTIHOMED;
1712 newts->cell = afs_GetCell(acell, 0);
1714 /* For each IP address we are registering */
1715 for (k = 0; k < nservers; k++) {
1716 iphash = SHash(aserverp[k]);
1718 /* Check if the srvAddr structure already exists. If so, remove
1719 * it from its server structure and add it to the new one.
1721 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1722 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1725 if (oldsa && (oldsa->server != newts)) {
1726 afs_RemoveSrvAddr(oldsa, tv); /* Remove from its server struct */
1727 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1728 newts->addr = oldsa;
1731 /* Reuse/allocate a new srvAddr structure */
1735 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1737 panic("malloc of srvAddr struct");
1738 afs_totalSrvAddrs++;
1739 memset(newsa, 0, sizeof(struct srvAddr));
1741 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1742 newsa->next_bkt = afs_srvAddrs[iphash];
1743 afs_srvAddrs[iphash] = newsa;
1745 /* Hang off of the server structure */
1746 newsa->next_sa = newts->addr;
1747 newts->addr = newsa;
1749 /* Initialize the srvAddr Structure */
1750 newsa->sa_ip = aserverp[k];
1751 newsa->sa_portal = aport;
1754 /* Update the srvAddr Structure */
1755 newsa->server = newts;
1756 if (newts->flags & SRVR_ISDOWN)
1757 newsa->sa_flags |= SRVADDR_ISDOWN;
1759 newsa->sa_flags |= SRVADDR_MH;
1761 newsa->sa_flags &= ~SRVADDR_MH;
1763 /* Compute preference values and resort */
1764 if (!newsa->sa_iprank) {
1765 afs_SetServerPrefs(newsa); /* new server rank */
1768 afs_SortOneServer(newts); /* Sort by rank */
1770 /* If we reused the server struct, remove any of its srvAddr
1771 * structs that will no longer be associated with this server.
1773 if (oldts) { /* reused the server struct */
1774 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1775 nextsa = orphsa->next_sa;
1776 for (k = 0; k < nservers; k++) {
1777 if (orphsa->sa_ip == aserverp[k])
1778 break; /* belongs */
1781 continue; /* belongs */
1783 /* Have a srvAddr struct. Now get a server struct (if not already) */
1785 orphts = afs_osi_Alloc(sizeof(struct server));
1787 panic("malloc of lo server struct");
1788 memset(orphts, 0, sizeof(struct server));
1791 /* Add the orphaned server to the afs_servers[] hash chain.
1792 * Its iphash does not matter since we never look up the server
1793 * in the afs_servers table by its ip address (only by uuid -
1794 * which this has none).
1796 iphash = SHash(aserverp[k]);
1797 orphts->next = afs_servers[iphash];
1798 afs_servers[iphash] = orphts;
1801 orphts->cell = afs_GetCell(acell, 0);
1804 /* Hang the srvAddr struct off of the server structure. The server
1805 * may have multiple srvAddrs, but it won't be marked multihomed.
1807 afs_RemoveSrvAddr(orphsa, tv); /* remove */
1808 orphsa->next_sa = orphts->addr; /* hang off server struct */
1809 orphts->addr = orphsa;
1810 orphsa->server = orphts;
1811 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1812 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1815 /* We can't need this below, and won't reacquire */
1816 ReleaseWriteLock(&afs_xvcb);
1818 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1820 struct afs_stats_SrvUpDownInfo *upDownP;
1821 /* With the introduction of this new record, we need to adjust the
1822 * proper individual & global server up/down info.
1824 upDownP = GetUpDownStats(newts);
1825 upDownP->numTtlRecords += srvcount;
1826 afs_stats_cmperf.srvRecords += srvcount;
1827 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1828 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1830 /* We can't need this below, and won't reacquire */
1831 ReleaseWriteLock(&afs_xvcb);
1833 ReleaseWriteLock(&afs_xsrvAddr);
1835 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1836 afs_GetCapabilities(newts);
1838 ReleaseWriteLock(&afs_xserver);
1840 } /* afs_GetServer */
1843 afs_ActivateServer(struct srvAddr *sap)
1845 osi_timeval_t currTime; /*Filled with current time */
1846 osi_timeval_t *currTimeP; /*Ptr to above */
1847 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1848 struct server *aserver = sap->server;
1850 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1852 * This server record has not yet been activated. Go for it,
1853 * recording its ``birth''.
1855 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1856 currTimeP = &currTime;
1857 osi_GetuTime(currTimeP);
1858 aserver->activationTime = currTime.tv_sec;
1859 upDownP = GetUpDownStats(aserver);
1860 if (aserver->flags & SRVR_ISDOWN) {
1861 upDownP->numDownRecords++;
1863 upDownP->numUpRecords++;
1864 upDownP->numRecordsNeverDown++;
1870 afs_RemoveAllConns(void)
1873 struct server *ts, *nts;
1876 ObtainReadLock(&afs_xserver);
1877 ObtainWriteLock(&afs_xconn, 1001);
1879 /*printf("Destroying connections ... ");*/
1880 for (i = 0; i < NSERVERS; i++) {
1881 for (ts = afs_servers[i]; ts; ts = nts) {
1883 for (sa = ts->addr; sa; sa = sa->next_sa) {
1885 afs_ReleaseConns(sa->conns);
1891 /*printf("done\n");*/
1893 ReleaseWriteLock(&afs_xconn);
1894 ReleaseReadLock(&afs_xserver);
1899 afs_MarkAllServersUp(void)
1905 ObtainWriteLock(&afs_xserver, 721);
1906 ObtainWriteLock(&afs_xsrvAddr, 722);
1907 for (i = 0; i< NSERVERS; i++) {
1908 for (ts = afs_servers[i]; ts; ts = ts->next) {
1909 for (sa = ts->addr; sa; sa = sa->next_sa) {
1910 afs_MarkServerUpOrDown(sa, 0);
1914 ReleaseWriteLock(&afs_xsrvAddr);
1915 ReleaseWriteLock(&afs_xserver);