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, int code)
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, code);
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, 0,
298 rx_SetConnDeadTime(rxconn, 3);
301 code = VL_ProbeServer(rxconn);
303 rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
304 afs_PutConn(tc, rxconn, SHARED_LOCK);
306 * If probe worked, or probe call not yet defined (for compatibility
307 * with old vlsevers), then we treat this server as running again
309 if (code == 0 || (code <= -450 && code >= -470)) {
310 if (tc->parent->srvr == sa) {
311 afs_MarkServerUpOrDown(sa, 0);
312 print_internet_address("afs: volume location server ", sa,
313 " is back up", 2, code);
320 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
321 #define AFS_MINCHANGE 2 /* min change we'll bother with */
323 #ifndef AFS_MAXCHANGEBACK
324 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
328 /*------------------------------------------------------------------------
329 * EXPORTED afs_CountServers
332 * Originally meant to count the number of servers and determining
333 * up/down info, this routine will now simply sum up all of the
334 * server record ages. All other up/down information is kept on the
344 * This routine locks afs_xserver for write for the duration.
347 * Set CM perf stats field sumOfRecordAges for all server record
349 *------------------------------------------------------------------------*/
352 afs_CountServers(void)
354 int currIdx; /*Curr idx into srv table */
355 struct server *currSrvP; /*Ptr to curr server record */
356 afs_int32 currChainLen; /*Length of curr hash chain */
357 osi_timeval_t currTime; /*Current time */
358 osi_timeval_t *currTimeP; /*Ptr to above */
359 afs_int32 srvRecordAge; /*Age of server record, in secs */
360 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
361 * info being manipulated */
364 * Write-lock the server table so we don't get any interference.
366 ObtainReadLock(&afs_xserver);
369 * Iterate over each hash index in the server table, walking down each
370 * chain and tallying what we haven't computed from the records there on
371 * the fly. First, though, initialize the tallies that will change.
373 afs_stats_cmperf.srvMaxChainLength = 0;
375 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
376 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
377 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
378 memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
379 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
381 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
382 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
383 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
384 memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
385 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
387 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
388 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
389 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
390 memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
391 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
393 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
394 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
395 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
396 memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
397 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
400 * Compute the current time, used to figure out server record ages.
402 currTimeP = &currTime;
403 osi_GetuTime(currTimeP);
406 * Sweep the server hash table, tallying all we need to know.
408 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
410 for (currSrvP = afs_servers[currIdx]; currSrvP;
411 currSrvP = currSrvP->next) {
413 * Bump the current chain length.
418 * Any further tallying for this record will only be done if it has
421 if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
422 && currSrvP->addr && currSrvP->cell) {
425 * Compute the current server record's age, then remember it
426 * in the appropriate places.
428 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
429 upDownP = GetUpDownStats(currSrvP);
430 upDownP->sumOfRecordAges += srvRecordAge;
431 if ((upDownP->ageOfYoungestRecord == 0)
432 || (srvRecordAge < upDownP->ageOfYoungestRecord))
433 upDownP->ageOfYoungestRecord = srvRecordAge;
434 if ((upDownP->ageOfOldestRecord == 0)
435 || (srvRecordAge > upDownP->ageOfOldestRecord))
436 upDownP->ageOfOldestRecord = srvRecordAge;
438 if (currSrvP->numDowntimeIncidents <=
439 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
440 (upDownP->downIncidents[0])++;
441 else if (currSrvP->numDowntimeIncidents <=
442 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
443 (upDownP->downIncidents[1])++;
444 else if (currSrvP->numDowntimeIncidents <=
445 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
446 (upDownP->downIncidents[2])++;
447 else if (currSrvP->numDowntimeIncidents <=
448 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
449 (upDownP->downIncidents[3])++;
450 else if (currSrvP->numDowntimeIncidents <=
451 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
452 (upDownP->downIncidents[4])++;
454 (upDownP->downIncidents[5])++;
457 } /*Current server has been active */
458 } /*Walk this chain */
461 * Before advancing to the next chain, remember facts about this one.
463 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
465 * We beat out the former champion (which was initially set to 0
466 * here). Mark down the new winner, and also remember if it's an
469 afs_stats_cmperf.srvMaxChainLength = currChainLen;
470 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
471 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
472 } /*Update chain length maximum */
473 } /*For each hash chain */
476 * We're done. Unlock the server table before returning to our caller.
478 ReleaseReadLock(&afs_xserver);
480 } /*afs_CountServers */
484 ForceAllNewConnections(void)
487 struct srvAddr **addrs;
491 ObtainReadLock(&afs_xserver); /* Necessary? */
492 ObtainReadLock(&afs_xsrvAddr);
495 for (i = 0; i < NSERVERS; i++) {
496 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
501 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
502 osi_Assert(addrs != NULL);
504 for (i = 0; i < NSERVERS; i++) {
505 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
506 if (j >= srvAddrCount)
512 ReleaseReadLock(&afs_xsrvAddr);
513 ReleaseReadLock(&afs_xserver);
514 for (i = 0; i < j; i++) {
516 ForceNewConnections(sa);
521 CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
527 for(i = 0; i < nconns; i++){
529 sa = tc->parent->srvr;
531 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
532 (tc->parent->srvr == sa)) {
534 print_internet_address("afs: file server ", sa, " is back up", 2,
537 ObtainWriteLock(&afs_xserver, 244);
538 ObtainWriteLock(&afs_xsrvAddr, 245);
539 afs_MarkServerUpOrDown(sa, 0);
540 ReleaseWriteLock(&afs_xsrvAddr);
541 ReleaseWriteLock(&afs_xserver);
543 if (afs_waitForeverCount) {
544 afs_osi_Wakeup(&afs_waitForever);
547 if (results[i] < 0) {
549 afs_ServerDown(sa, results[i]);
550 ForceNewConnections(sa); /* multi homed clients */
557 CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
558 struct afs_conn **conns)
565 caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
566 osi_Assert(caps != NULL);
567 memset(caps, 0, nconns * sizeof(Capabilities));
569 results = afs_osi_Alloc(nconns * sizeof (afs_int32));
570 osi_Assert(results != NULL);
573 multi_Rx(rxconns,nconns)
575 multi_RXAFS_GetCapabilities(&caps[multi_i]);
576 results[multi_i] = multi_error;
580 for ( i = 0 ; i < nconns ; i++ ) {
581 ts = conns[i]->parent->srvr->server;
584 ts->capabilities = 0;
585 ts->flags |= SCAPS_KNOWN;
586 if ( results[i] == RXGEN_OPCODE ) {
587 /* Mark server as up - it responded */
591 if ( results[i] >= 0 )
592 /* we currently handle 32-bits of capabilities */
593 if (caps[i].Capabilities_len > 0) {
594 ts->capabilities = caps[i].Capabilities_val[0];
595 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
596 caps[i].Capabilities_val = NULL;
597 caps[i].Capabilities_len = 0;
600 CkSrv_MarkUpDown(conns, nconns, results);
602 afs_osi_Free(caps, nconns * sizeof(Capabilities));
603 afs_osi_Free(results, nconns * sizeof(afs_int32));
606 /* check down servers (if adown), or running servers (if !adown) */
608 afs_CheckServers(int adown, struct cell *acellp)
610 afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
613 /* adown: AFS_LS_UP - check only up
614 * AFS_LS_DOWN - check only down.
615 * AFS_LS_ALL - check all */
617 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
618 void (*func1) (int nservers, struct rx_connection **rxconns,
619 struct afs_conn **conns),
620 void (*func2) (int nservers, struct rx_connection **rxconns,
621 struct afs_conn **conns))
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;
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 if ((code = afs_InitReq(&treq, afs_osi_credp)))
648 ObtainReadLock(&afs_xserver); /* Necessary? */
649 ObtainReadLock(&afs_xsrvAddr);
652 for (i = 0; i < NSERVERS; i++) {
653 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
658 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
659 osi_Assert(addrs != NULL);
661 for (i = 0; i < NSERVERS; i++) {
662 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
663 if (j >= srvAddrCount)
669 ReleaseReadLock(&afs_xsrvAddr);
670 ReleaseReadLock(&afs_xserver);
672 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
673 osi_Assert(conns != NULL);
674 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
675 osi_Assert(rxconns != NULL);
676 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
677 osi_Assert(conntimer != NULL);
680 for (i = 0; i < j; i++) {
681 struct rx_connection *rxconn;
687 /* See if a cell to check was specified. If it is spec'd and not
688 * this server's cell, just skip the server.
690 if (acellp && acellp != ts->cell)
693 if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
694 || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
697 /* check vlserver with special code */
698 if (sa->sa_portal == AFS_VLPORT) {
700 CheckVLServer(sa, &treq);
704 if (!ts->cell) /* not really an active server, anyway, it must */
705 continue; /* have just been added by setsprefs */
707 /* get a connection, even if host is down; bumps conn ref count */
708 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
709 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
710 1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
712 afs_PutUser(tu, SHARED_LOCK);
716 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
718 rxconns[nconns]=rxconn;
719 if (sa->sa_flags & SRVADDR_ISDOWN) {
720 rx_SetConnDeadTime(rxconn, 3);
726 } else /* not holding, kill ref */
727 afs_PutConn(tc, rxconn, SHARED_LOCK);
728 } /* Outer loop over addrs */
730 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
733 (*func1)(nconns, rxconns, conns);
736 (*func2)(nconns, rxconns, conns);
739 for (i = 0; i < nconns; i++) {
740 if (conntimer[i] == 1)
741 rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
742 afs_PutConn(conns[i], rxconns[i], SHARED_LOCK); /* done with it now */
745 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
746 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
747 afs_osi_Free(conntimer, j * sizeof(afs_int32));
749 } /*afs_CheckServers*/
752 /* find a server structure given the host address */
754 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
761 AFS_STATCNT(afs_FindServer);
763 i = afs_uuid_hash(uuidp) % NSERVERS;
764 for (ts = afs_servers[i]; ts; ts = ts->next) {
765 if ((ts->flags & SRVR_MULTIHOMED)
767 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
768 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
773 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
774 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
781 } /*afs_FindServer */
784 /* some code for creating new server structs and setting preferences follows
785 * in the next few lines...
788 #define MAXDEFRANK 60000
789 #define DEFRANK 40000
791 /* Random number generator and constants from KnuthV2 2d ed, p170 */
797 a is 0.73m should be 0.01m .. 0.99m
798 c is more or less immaterial. 1 or a is suggested.
800 NB: LOW ORDER BITS are not very random. To get small random numbers,
801 treat result as <1, with implied binary point, and multiply by
803 NB: Has to be unsigned, since shifts on signed quantities may preserve
806 /* added rxi_getaddr() to try to get as much initial randomness as
807 possible, since at least one customer reboots ALL their clients
808 simultaneously -- so osi_Time is bound to be the same on some of the
809 clients. This is probably OK, but I don't want to see too much of it.
812 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
817 static afs_int32 state = 0;
820 AFS_STATCNT(afs_random);
825 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
826 * bits are in a tv_usec
828 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
829 state += (t.tv_sec & 0xff);
830 for (i = 0; i < 30; i++) {
840 /* returns int 0..14 using the high bits of a pseudo-random number instead of
841 the low bits, as the low bits are "less random" than the high ones...
842 slight roundoff error exists, an excercise for the reader.
843 need to multiply by something with lots of ones in it, so multiply by
844 8 or 16 is right out.
847 afs_randomMod15(void)
851 temp = afs_random() >> 4;
852 temp = (temp * 15) >> 28;
858 afs_randomMod127(void)
862 temp = afs_random() >> 7;
863 temp = (temp * 127) >> 25;
868 /* afs_SortOneServer()
869 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
872 afs_SortOneServer(struct server *asp)
874 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
877 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
879 lowsa = *rootsa; /* lowest sa is the first one */
880 lowrank = lowsa->sa_iprank;
882 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
883 rank = tsa->next_sa->sa_iprank;
884 if (rank < lowrank) {
886 lowsa = tsa->next_sa;
887 lowrank = lowsa->sa_iprank;
890 if (lowprev) { /* found one lower, so rearrange them */
891 lowprev->next_sa = lowsa->next_sa;
892 lowsa->next_sa = *rootsa;
899 * Sort the pointer to servers by the server's rank (its lowest rank).
900 * It is assumed that the server already has its IP addrs sorted (the
901 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
904 afs_SortServers(struct server *aservers[], int count)
909 AFS_STATCNT(afs_SortServers);
911 for (i = 0; i < count; i++) {
914 for (low = i, j = i + 1; j <= count; j++) {
915 if ((!aservers[j]) || (!aservers[j]->addr))
917 if ((!aservers[low]) || (!aservers[low]->addr))
919 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
925 aservers[i] = aservers[low];
929 } /*afs_SortServers */
931 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
932 data structures to determine what the local IP addresses and subnet masks
933 are in order to choose which server(s) are on the local subnet.
935 As I see it, there are several cases:
936 1. The server address is one of this host's local addresses. In this case
937 this server is to be preferred over all others.
938 2. The server is on the same subnet as one of the this host's local
939 addresses. (ie, an odd-sized subnet, not class A,B,orC)
940 3. The server is on the same net as this host (class A,B or C)
941 4. The server is on a different logical subnet or net than this host, but
942 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
944 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
946 6. This host and the server are disjoint.
948 That is a rough order of preference. If a point-to-point link has a high
949 metric, I'm assuming that it is a very slow link, and putting it at the
950 bottom of the list (at least until RX works better over slow links). If
951 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
953 It's not easy to check for case #4, so I'm ignoring it for the time being.
955 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
956 That could be used to prefer certain servers fairly easily. Maybe some
959 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
960 protocols (well, addresses that are stored in uint32s, at any rate).
963 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
964 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
966 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
967 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
972 #define PPWEIGHT 4096
976 #ifdef AFS_USERSPACE_IP_ADDR
978 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
981 * The IP addresses and ranks are determined by afsd (in user space) and
982 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
983 * system call. These are stored in the data structure
984 * called 'afs_cb_interface'.
986 * struct srvAddr *sa; remote server
987 * afs_int32 addr; one of my local addr in net order
988 * afs_uint32 subnetmask; subnet mask of local addr in net order
992 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
993 afs_uint32 subnetmask)
995 afs_uint32 myAddr, myNet, mySubnet, netMask;
996 afs_uint32 serverAddr;
998 myAddr = ntohl(addr); /* one of my IP addr in host order */
999 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1000 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1002 if (IN_CLASSA(myAddr))
1003 netMask = IN_CLASSA_NET;
1004 else if (IN_CLASSB(myAddr))
1005 netMask = IN_CLASSB_NET;
1006 else if (IN_CLASSC(myAddr))
1007 netMask = IN_CLASSC_NET;
1011 myNet = myAddr & netMask;
1012 mySubnet = myAddr & subnetmask;
1014 if ((serverAddr & netMask) == myNet) {
1015 if ((serverAddr & subnetmask) == mySubnet) {
1016 if (serverAddr == myAddr) { /* same machine */
1017 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1018 } else { /* same subnet */
1019 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1021 } else { /* same net */
1022 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1027 #else /* AFS_USERSPACE_IP_ADDR */
1028 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && (! defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1030 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1032 struct sockaddr_in *sin;
1035 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1036 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1038 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1039 sa->sa_iprank = TOPR;
1041 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1042 if (sa->sa_iprank > t)
1046 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1047 if (sa->sa_iprank > t)
1051 #if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
1052 /* check for case #4 -- point-to-point link */
1053 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1054 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1055 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1058 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1059 if (sa->sa_iprank > t)
1062 #endif /* IFF_POINTOPOINT */
1064 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1065 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV) || defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1067 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1070 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1072 struct sockaddr sout;
1073 struct sockaddr_in *sin;
1074 #if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
1080 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1081 afs_uint32 serverAddr;
1083 if (rx_ifaddr_address_family(ifa) != AF_INET)
1085 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1087 sin = (struct sockaddr_in *)&sout;
1088 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1092 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1093 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1095 sin = (struct sockaddr_in *)&sout;
1096 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1100 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1102 sin = (struct sockaddr_in *)&sout;
1103 myDstaddr = ntohl(sin->sin_addr.s_addr);
1108 if (IN_CLASSA(myAddr))
1109 netMask = IN_CLASSA_NET;
1110 else if (IN_CLASSB(myAddr))
1111 netMask = IN_CLASSB_NET;
1112 else if (IN_CLASSC(myAddr))
1113 netMask = IN_CLASSC_NET;
1117 myNet = myAddr & netMask;
1118 mySubnet = myAddr & subnetmask;
1120 if ((serverAddr & netMask) == myNet) {
1121 if ((serverAddr & subnetmask) == mySubnet) {
1122 if (serverAddr == myAddr) { /* same machine */
1123 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1124 } else { /* same subnet */
1125 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1127 } else { /* same net */
1128 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1131 #ifdef IFF_POINTTOPOINT
1132 /* check for case #4 -- point-to-point link */
1133 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1134 && (myDstaddr == serverAddr)) {
1135 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1138 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1139 if (sa->sa_iprank > t)
1142 #endif /* IFF_POINTTOPOINT */
1144 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1145 #endif /* else AFS_USERSPACE_IP_ADDR */
1147 #ifdef AFS_SGI62_ENV
1149 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1152 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1153 return 0; /* Never match, so we enumerate everyone */
1155 #endif /* AFS_SGI62_ENV */
1157 afs_SetServerPrefs(struct srvAddr *const sa)
1159 #if defined(AFS_USERSPACE_IP_ADDR)
1163 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1164 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1165 afs_cb_interface.subnetmask[i]);
1167 #else /* AFS_USERSPACE_IP_ADDR */
1168 #if defined(AFS_SUN5_ENV)
1169 #ifdef AFS_SUN510_ENV
1172 extern struct ill_s *ill_g_headp;
1173 long *addr = (long *)ill_g_headp;
1177 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;
1197 /* XXXXXX Do the individual ip ranking below XXXXX */
1198 if ((sa->sa_ip & netmask) == net) {
1199 if ((sa->sa_ip & subnetmask) == subnet) {
1200 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1201 sa->sa_iprank = TOPR;
1203 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1206 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1209 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1211 /* check for case #5 -- point-to-point link */
1212 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1213 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1215 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1216 sa->sa_iprank = MAXDEFRANK;
1218 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1223 rw_exit(&afsifinfo_lock);
1225 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1226 ill = ill->ill_next) {
1227 /* Make sure this is an IPv4 ILL */
1230 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1231 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1232 subnetmask = ipif->ipif_net_mask;
1234 * Generate the local net using the local address and
1235 * whate we know about Class A, B and C networks.
1237 if (IN_CLASSA(ipif->ipif_local_addr)) {
1238 netmask = IN_CLASSA_NET;
1239 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1240 netmask = IN_CLASSB_NET;
1241 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1242 netmask = IN_CLASSC_NET;
1246 net = ipif->ipif_local_addr & netmask;
1248 /* XXXXXX Do the individual ip ranking below XXXXX */
1249 if ((sa->sa_ip & netmask) == net) {
1250 if ((sa->sa_ip & subnetmask) == subnet) {
1251 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1252 sa->sa_iprank = TOPR;
1254 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1257 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1260 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1262 /* check for case #5 -- point-to-point link */
1263 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1264 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1266 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1267 sa->sa_iprank = MAXDEFRANK;
1269 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1274 #endif /* AFS_SUN510_ENV */
1277 rx_ifnet_t ifn = NULL;
1278 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1279 struct sockaddr_in *sin;
1282 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1283 if (ifn) { /* local, more or less */
1285 if (ifn->if_flags & IFF_LOOPBACK) {
1286 sa->sa_iprank = TOPR;
1289 #endif /* IFF_LOOPBACK */
1290 sin = (struct sockaddr_in *)IA_SIN(ifad);
1291 if (SA2ULONG(sin) == sa->sa_ip) {
1292 sa->sa_iprank = TOPR;
1295 #ifdef IFF_BROADCAST
1296 if (ifn->if_flags & IFF_BROADCAST) {
1297 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1302 #endif /* IFF_BROADCAST */
1303 #ifdef IFF_POINTOPOINT
1304 if (ifn->if_flags & IFF_POINTOPOINT) {
1305 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1306 if (ifn->if_metric > 4) {
1310 sa->sa_iprank = ifn->if_metric;
1313 #endif /* IFF_POINTOPOINT */
1314 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1316 #else /* USEIFADDR */
1319 #ifdef AFS_SGI62_ENV
1320 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1321 (caddr_t) sa, NULL);
1322 #elif defined(AFS_DARWIN80_ENV)
1330 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1331 for (m = 0; m < count; m++) {
1332 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1333 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1334 afsi_SetServerIPRank(sa, ifads[j]);
1337 ifnet_free_address_list(ifads);
1340 ifnet_list_free(ifns);
1343 #elif defined(AFS_DARWIN_ENV)
1347 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1348 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1349 afsi_SetServerIPRank(sa, ifa);
1351 #elif defined(AFS_FBSD_ENV)
1353 struct in_ifaddr *ifa;
1354 #if defined(AFS_FBSD80_ENV)
1355 TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
1357 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1359 afsi_SetServerIPRank(sa, &ifa->ia_ifa);
1361 #elif defined(AFS_OBSD_ENV)
1363 extern struct in_ifaddrhead in_ifaddr;
1364 struct in_ifaddr *ifa;
1365 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1366 afsi_SetServerIPRank(sa, ifa);
1368 #elif defined(AFS_NBSD40_ENV)
1370 extern struct in_ifaddrhead in_ifaddrhead;
1371 struct in_ifaddr *ifa;
1372 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1373 afsi_SetServerIPRank(sa, ifa);
1377 struct in_ifaddr *ifa;
1378 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1379 afsi_SetServerIPRank(sa, ifa);
1382 #endif /* USEIFADDR */
1386 #endif /* AFS_SUN5_ENV */
1387 #endif /* else AFS_USERSPACE_IP_ADDR */
1388 sa->sa_iprank += afs_randomMod15();
1391 } /* afs_SetServerPrefs */
1399 /* afs_FlushServer()
1400 * The addresses on this server struct has changed in some way and will
1401 * clean up all other structures that may reference it.
1402 * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
1405 afs_FlushServer(struct server *srvp, struct volume *tv)
1408 struct server *ts, **pts;
1410 /* Find any volumes residing on this server and flush their state */
1411 afs_ResetVolumes(srvp, tv);
1413 /* Flush all callbacks in the all vcaches for this specific server */
1414 afs_FlushServerCBs(srvp);
1416 /* Remove all the callbacks structs */
1418 struct afs_cbr *cb, *cbnext;
1420 for (cb = srvp->cbrs; cb; cb = cbnext) {
1423 } srvp->cbrs = (struct afs_cbr *)0;
1426 /* If no more srvAddr structs hanging off of this server struct,
1430 /* Remove the server structure from the cell list - if there */
1431 afs_RemoveCellEntry(srvp);
1433 /* Remove from the afs_servers hash chain */
1434 for (i = 0; i < NSERVERS; i++) {
1435 for (pts = &(afs_servers[i]), ts = *pts; ts;
1436 pts = &(ts->next), ts = *pts) {
1444 *pts = ts->next; /* Found it. Remove it */
1445 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1451 /* afs_RemoveSrvAddr()
1452 * This removes a SrvAddr structure from its server structure.
1453 * The srvAddr struct is not free'd because it connections may still
1454 * be open to it. It is up to the calling process to make sure it
1455 * remains connected to a server struct.
1456 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1457 * It is not removed from the afs_srvAddrs hash chain.
1458 * If resetting volumes, do not reset volume tv
1461 afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
1463 struct srvAddr **psa, *sa;
1470 /* Find the srvAddr in the server's list and remove it */
1471 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1479 /* Flush the server struct since it's IP address has changed */
1480 afs_FlushServer(srv, tv);
1484 /* afs_GetCapabilities
1485 * Try and retrieve capabilities of a given file server. Carps on actual
1486 * failure. Servers are not expected to support this RPC. */
1488 afs_GetCapabilities(struct server *ts)
1490 Capabilities caps = {0, NULL};
1491 struct vrequest treq;
1492 struct afs_conn *tc;
1493 struct unixuser *tu;
1494 struct rx_connection *rxconn;
1497 if ( !ts || !ts->cell )
1499 if ( !afs_osi_credp )
1502 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1504 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1507 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1508 SHARED_LOCK, 0, &rxconn);
1509 afs_PutUser(tu, SHARED_LOCK);
1512 /* InitCallBackStateN, triggered by our RPC, may need this */
1513 ReleaseWriteLock(&afs_xserver);
1514 code = RXAFS_GetCapabilities(rxconn, &caps);
1515 ObtainWriteLock(&afs_xserver, 723);
1516 /* we forced a conn above; important we mark it down if needed */
1517 if ((code < 0) && (code != RXGEN_OPCODE)) {
1518 afs_ServerDown(tc->parent->srvr, code);
1519 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1521 afs_PutConn(tc, rxconn, SHARED_LOCK);
1522 if ( code && code != RXGEN_OPCODE ) {
1523 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1524 /* better not be anything to free. we failed! */
1528 ts->flags |= SCAPS_KNOWN;
1530 if ( caps.Capabilities_len > 0 ) {
1531 ts->capabilities = caps.Capabilities_val[0];
1532 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1533 caps.Capabilities_len = 0;
1534 caps.Capabilities_val = NULL;
1539 static struct server *
1540 afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
1541 struct server **oldts, afs_int32 addr_uniquifier)
1543 struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
1544 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1545 /* Found a server struct that is multihomed and same
1546 * uniqufier (same IP addrs). The above if statement is the
1547 * same as in InstallUVolumeEntry().
1552 *oldts = ts; /* Will reuse if same uuid */
1557 * Return an updated and properly initialized server structure.
1559 * Takes a server ID, cell, and port.
1560 * If server does not exist, then one will be created.
1561 * @param[in] aserverp
1562 * The server address in network byte order
1563 * @param[in] nservers
1564 * The number of IP addresses claimed by the server
1566 * The cell the server is in
1568 * The port for the server (fileserver or vlserver) in network byte order
1569 * @param[in] locktype
1570 * The type of lock to hold when iterating server hash (unused).
1572 * The uuid for servers supporting one.
1573 * @param[in] addr_uniquifier
1574 * The vldb-provider per-instantiated-server uniquifer counter.
1576 * A volume not to reset information for if the server addresses
1580 * A server structure matching the request.
1583 afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
1584 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1585 afs_int32 addr_uniquifier, struct volume *tv)
1587 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1588 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1589 afs_int32 iphash, k, srvcount = 0;
1590 unsigned int srvhash;
1592 AFS_STATCNT(afs_GetServer);
1594 ObtainSharedLock(&afs_xserver, 13);
1596 /* Check if the server struct exists and is up to date */
1599 panic("afs_GetServer: incorrect count of servers");
1600 ObtainReadLock(&afs_xsrvAddr);
1601 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1602 ReleaseReadLock(&afs_xsrvAddr);
1603 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1604 /* Found a server struct that is not multihomed and has the
1605 * IP address associated with it. A correct match.
1607 ReleaseSharedLock(&afs_xserver);
1612 panic("afs_GetServer: incorrect count of servers");
1614 ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
1616 ReleaseSharedLock(&afs_xserver);
1622 * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
1623 * Do a little dance and see if we can grab xvcb. If not, we
1624 * need to recheck that oldts is still right after a drop and reobtain.
1626 if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
1627 ReleaseSharedLock(&afs_xserver);
1628 ObtainWriteLock(&afs_xvcb, 299);
1629 ObtainWriteLock(&afs_xserver, 35);
1631 /* we don't know what changed while we didn't hold the lock */
1633 ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
1636 ReleaseWriteLock(&afs_xserver);
1637 ReleaseWriteLock(&afs_xvcb);
1641 UpgradeSToWLock(&afs_xserver, 36);
1643 ObtainWriteLock(&afs_xsrvAddr, 116);
1644 srvcount = afs_totalServers;
1646 /* Reuse/allocate a new server structure */
1650 newts = afs_osi_Alloc(sizeof(struct server));
1652 panic("malloc of server struct");
1654 memset(newts, 0, sizeof(struct server));
1656 /* Add the server struct to the afs_servers[] hash chain */
1658 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1659 newts->next = afs_servers[srvhash];
1660 afs_servers[srvhash] = newts;
1663 /* Initialize the server structure */
1664 if (uuidp) { /* Multihomed */
1665 newts->sr_uuid = *uuidp;
1666 newts->sr_addr_uniquifier = addr_uniquifier;
1667 newts->flags |= SRVR_MULTIHOMED;
1670 newts->cell = afs_GetCell(acell, 0);
1672 /* For each IP address we are registering */
1673 for (k = 0; k < nservers; k++) {
1674 iphash = SHash(aserverp[k]);
1676 /* Check if the srvAddr structure already exists. If so, remove
1677 * it from its server structure and add it to the new one.
1679 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1680 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1683 if (oldsa && (oldsa->server != newts)) {
1684 afs_RemoveSrvAddr(oldsa, tv); /* Remove from its server struct */
1685 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1686 newts->addr = oldsa;
1689 /* Reuse/allocate a new srvAddr structure */
1693 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1695 panic("malloc of srvAddr struct");
1696 afs_totalSrvAddrs++;
1697 memset(newsa, 0, sizeof(struct srvAddr));
1699 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1700 newsa->next_bkt = afs_srvAddrs[iphash];
1701 afs_srvAddrs[iphash] = newsa;
1703 /* Hang off of the server structure */
1704 newsa->next_sa = newts->addr;
1705 newts->addr = newsa;
1707 /* Initialize the srvAddr Structure */
1708 newsa->sa_ip = aserverp[k];
1709 newsa->sa_portal = aport;
1712 /* Update the srvAddr Structure */
1713 newsa->server = newts;
1714 if (newts->flags & SRVR_ISDOWN)
1715 newsa->sa_flags |= SRVADDR_ISDOWN;
1717 newsa->sa_flags |= SRVADDR_MH;
1719 newsa->sa_flags &= ~SRVADDR_MH;
1721 /* Compute preference values and resort */
1722 if (!newsa->sa_iprank) {
1723 afs_SetServerPrefs(newsa); /* new server rank */
1726 afs_SortOneServer(newts); /* Sort by rank */
1728 /* If we reused the server struct, remove any of its srvAddr
1729 * structs that will no longer be associated with this server.
1731 if (oldts) { /* reused the server struct */
1732 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1733 nextsa = orphsa->next_sa;
1734 for (k = 0; k < nservers; k++) {
1735 if (orphsa->sa_ip == aserverp[k])
1736 break; /* belongs */
1739 continue; /* belongs */
1741 /* Have a srvAddr struct. Now get a server struct (if not already) */
1743 orphts = afs_osi_Alloc(sizeof(struct server));
1745 panic("malloc of lo server struct");
1746 memset(orphts, 0, sizeof(struct server));
1749 /* Add the orphaned server to the afs_servers[] hash chain.
1750 * Its iphash does not matter since we never look up the server
1751 * in the afs_servers table by its ip address (only by uuid -
1752 * which this has none).
1754 iphash = SHash(aserverp[k]);
1755 orphts->next = afs_servers[iphash];
1756 afs_servers[iphash] = orphts;
1759 orphts->cell = afs_GetCell(acell, 0);
1762 /* Hang the srvAddr struct off of the server structure. The server
1763 * may have multiple srvAddrs, but it won't be marked multihomed.
1765 afs_RemoveSrvAddr(orphsa, tv); /* remove */
1766 orphsa->next_sa = orphts->addr; /* hang off server struct */
1767 orphts->addr = orphsa;
1768 orphsa->server = orphts;
1769 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1770 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1773 /* We can't need this below, and won't reacquire */
1774 ReleaseWriteLock(&afs_xvcb);
1776 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1778 struct afs_stats_SrvUpDownInfo *upDownP;
1779 /* With the introduction of this new record, we need to adjust the
1780 * proper individual & global server up/down info.
1782 upDownP = GetUpDownStats(newts);
1783 upDownP->numTtlRecords += srvcount;
1784 afs_stats_cmperf.srvRecords += srvcount;
1785 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1786 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1788 /* We can't need this below, and won't reacquire */
1789 ReleaseWriteLock(&afs_xvcb);
1791 ReleaseWriteLock(&afs_xsrvAddr);
1793 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1794 afs_GetCapabilities(newts);
1796 ReleaseWriteLock(&afs_xserver);
1798 } /* afs_GetServer */
1801 afs_ActivateServer(struct srvAddr *sap)
1803 osi_timeval_t currTime; /*Filled with current time */
1804 osi_timeval_t *currTimeP; /*Ptr to above */
1805 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1806 struct server *aserver = sap->server;
1808 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1810 * This server record has not yet been activated. Go for it,
1811 * recording its ``birth''.
1813 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1814 currTimeP = &currTime;
1815 osi_GetuTime(currTimeP);
1816 aserver->activationTime = currTime.tv_sec;
1817 upDownP = GetUpDownStats(aserver);
1818 if (aserver->flags & SRVR_ISDOWN) {
1819 upDownP->numDownRecords++;
1821 upDownP->numUpRecords++;
1822 upDownP->numRecordsNeverDown++;
1828 afs_RemoveAllConns(void)
1831 struct server *ts, *nts;
1834 ObtainReadLock(&afs_xserver);
1835 ObtainWriteLock(&afs_xconn, 1001);
1837 /*printf("Destroying connections ... ");*/
1838 for (i = 0; i < NSERVERS; i++) {
1839 for (ts = afs_servers[i]; ts; ts = nts) {
1841 for (sa = ts->addr; sa; sa = sa->next_sa) {
1843 afs_ReleaseConns(sa->conns);
1850 /*printf("done\n");*/
1852 ReleaseWriteLock(&afs_xconn);
1853 ReleaseReadLock(&afs_xserver);
1858 afs_MarkAllServersUp(void)
1864 ObtainWriteLock(&afs_xserver, 721);
1865 ObtainWriteLock(&afs_xsrvAddr, 722);
1866 for (i = 0; i< NSERVERS; i++) {
1867 for (ts = afs_servers[i]; ts; ts = ts->next) {
1868 for (sa = ts->addr; sa; sa = sa->next_sa) {
1869 afs_MarkServerUpOrDown(sa, 0);
1873 ReleaseWriteLock(&afs_xsrvAddr);
1874 ReleaseWriteLock(&afs_xserver);