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/stds.h"
38 #include "../afs/sysincludes.h" /* Standard vendor system headers */
42 #include <netinet/in.h>
45 #include "../h/hashing.h"
47 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV)
48 #include <netinet/in_var.h>
49 #endif /* AFS_HPUX110_ENV */
50 #endif /* !defined(UKERNEL) */
52 #include "../afs/afsincludes.h" /* Afs-based standard headers */
53 #include "../afs/afs_stats.h" /* afs statistics */
55 #if defined(AFS_SUN56_ENV)
57 #include <inet/common.h>
58 #if defined(AFS_SUN58_ENV)
59 # include <netinet/ip6.h>
60 # define ipif_local_addr ipif_lcl_addr
61 # ifndef V4_PART_OF_V6
62 # define V4_PART_OF_V6(v6) v6.s6_addr32[3]
68 /* Imported variables */
69 extern afs_int32 afs_setTime;
70 extern afs_int32 afs_waitForever;
71 extern short afs_waitForeverCount;
74 /* Exported variables */
75 afs_rwlock_t afs_xserver; /* allocation lock for servers */
76 struct server *afs_setTimeHost=0; /* last host we used for time */
77 struct server *afs_servers[NSERVERS]; /* Hashed by server`s uuid & 1st ip */
78 afs_rwlock_t afs_xsrvAddr; /* allocation lock for srvAddrs */
79 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
82 /* debugging aids - number of alloc'd server and srvAddr structs. */
83 int afs_reuseServers = 0;
84 int afs_reuseSrvAddrs = 0;
85 int afs_totalServers = 0;
86 int afs_totalSrvAddrs = 0;
91 /*------------------------------------------------------------------------
92 * afs_MarkServerUpOrDown
95 * Mark the given server up or down, and track its uptime stats.
98 * a_serverP : Ptr to server record to fiddle with.
99 * a_isDown : Is the server is to be marked down?
105 * The CM server structures must be write-locked.
109 *------------------------------------------------------------------------*/
111 void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
113 register struct server *a_serverP = sa->server;
114 register struct srvAddr *sap;
115 osi_timeval_t currTime, *currTimeP; /*Current time*/
116 afs_int32 downTime; /*Computed downtime, in seconds*/
117 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
120 * If the server record is marked the same as the new status we've
121 * been fed, then there isn't much to be done.
123 if (( a_isDown && (sa->sa_flags & SRVADDR_ISDOWN)) ||
124 (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
128 sa->sa_flags |= SRVADDR_ISDOWN;
129 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
130 if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
131 /* Not all ips are up so don't bother with the
132 * server's up/down stats */
137 * All ips are down we treat the whole server down
139 a_serverP->flags |= SRVR_ISDOWN;
141 * If this was our time server, search for another time server
143 if (a_serverP == afs_setTimeHost)
146 sa->sa_flags &= ~SRVADDR_ISDOWN;
147 /* If any ips are up, the server is also marked up */
148 a_serverP->flags &= ~SRVR_ISDOWN;
149 for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
150 if (sap->sa_flags & SRVADDR_ISDOWN) {
151 /* Not all ips are up so don't bother with the
152 * server's up/down stats */
159 * Compute the current time and which overall stats record is to be
160 * updated; we'll need them one way or another.
162 currTimeP = &currTime;
163 osi_GetuTime(currTimeP);
165 if (sa->sa_portal == AFS_FSPORT) {
166 upDownP = (a_serverP->cell->cell == 1) ?
167 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
168 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
169 } /*File Server record*/
171 upDownP = (a_serverP->cell->cell == 1) ?
172 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
173 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
174 } /*VL Server record*/
178 * Server going up -> down; remember the beginning of this
181 a_serverP->lastDowntimeStart = currTime.tv_sec;
183 (upDownP->numDownRecords)++;
184 (upDownP->numUpRecords)--;
185 } /*Server being marked down*/
188 * Server going down -> up; remember everything about this
189 * newly-completed downtime incident.
191 downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
192 (a_serverP->numDowntimeIncidents)++;
193 a_serverP->sumOfDowntimes += downTime;
195 (upDownP->numUpRecords)++;
196 (upDownP->numDownRecords)--;
197 (upDownP->numDowntimeIncidents)++;
198 if (a_serverP->numDowntimeIncidents == 1)
199 (upDownP->numRecordsNeverDown)--;
200 upDownP->sumOfDowntimes += downTime;
201 if ((upDownP->shortestDowntime == 0) ||
202 (downTime < upDownP->shortestDowntime))
203 upDownP->shortestDowntime = downTime;
204 if ((upDownP->longestDowntime == 0) ||
205 (downTime > upDownP->longestDowntime))
206 upDownP->longestDowntime = downTime;
209 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
210 (upDownP->downDurations[0])++;
212 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
213 (upDownP->downDurations[1])++;
215 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
216 (upDownP->downDurations[2])++;
218 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
219 (upDownP->downDurations[3])++;
221 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
222 (upDownP->downDurations[4])++;
224 if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
225 (upDownP->downDurations[5])++;
227 (upDownP->downDurations[6])++;
229 } /*Server being marked up*/
231 } /*MarkServerUpOrDown*/
234 void afs_ServerDown(struct srvAddr *sa)
236 register struct server *aserver = sa->server;
237 register struct srvAddr *sap;
239 AFS_STATCNT(ServerDown);
240 if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
242 afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
243 if (sa->sa_portal == aserver->cell->vlport)
244 print_internet_address("afs: Lost contact with volume location server ",
247 print_internet_address("afs: Lost contact with file server ", sa, "", 1);
252 /* return true if we have any callback promises from this server */
253 static HaveCallBacksFrom(aserver)
254 struct server *aserver;
257 register afs_int32 now;
259 register struct vcache *tvc;
261 AFS_STATCNT(HaveCallBacksFrom);
262 now = osi_Time(); /* for checking for expired callbacks */
263 for(i=0;i<VCSIZE;i++) { /* for all guys in the hash table */
264 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
266 * Check to see if this entry has an unexpired callback promise
267 * from the required host
269 if (aserver == tvc->callback && tvc->cbExpires >= now
270 && ((tvc->states & CRO) == 0))
276 } /*HaveCallBacksFrom*/
279 static void CheckVLServer(sa, areq)
280 struct vrequest *areq;
281 register struct srvAddr *sa;
283 register struct server *aserver = sa->server;
284 register struct conn *tc;
285 register afs_int32 code;
287 AFS_STATCNT(CheckVLServer);
288 /* Ping dead servers to see if they're back */
289 if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN)) || (aserver->flags & SRVR_ISGONE))
292 return; /* can't do much */
294 tc = afs_ConnByHost(aserver, aserver->cell->vlport,
295 aserver->cell->cell, areq, 1, SHARED_LOCK);
298 rx_SetConnDeadTime(tc->id, 3);
301 code = VL_ProbeServer(tc->id);
303 rx_SetConnDeadTime(tc->id, 50);
304 afs_PutConn(tc, 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->srvr == sa) {
311 afs_MarkServerUpOrDown(sa, 0);
312 print_internet_address("afs: volume location server ",
313 sa, " is back up", 2);
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 *------------------------------------------------------------------------*/
351 void afs_CountServers()
353 { /*afs_CountServers*/
355 int currIdx; /*Curr idx into srv table*/
356 struct server *currSrvP; /*Ptr to curr server record*/
357 afs_int32 currChainLen; /*Length of curr hash chain*/
358 osi_timeval_t currTime; /*Current time*/
359 osi_timeval_t *currTimeP; /*Ptr to above*/
360 afs_int32 srvRecordAge; /*Age of server record, in secs*/
361 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
362 info being manipulated*/
365 * Write-lock the server table so we don't get any interference.
367 ObtainReadLock(&afs_xserver);
370 * Iterate over each hash index in the server table, walking down each
371 * chain and tallying what we haven't computed from the records there on
372 * the fly. First, though, initialize the tallies that will change.
374 afs_stats_cmperf.srvMaxChainLength = 0;
376 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
377 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
378 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
379 memset((char *) afs_stats_cmperf.fs_UpDown[0].downIncidents, 0, 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((char *) afs_stats_cmperf.fs_UpDown[1].downIncidents, 0, 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((char *) afs_stats_cmperf.vl_UpDown[0].downIncidents, 0, AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
391 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
392 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
393 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
394 memset((char *) afs_stats_cmperf.vl_UpDown[1].downIncidents, 0, AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
397 * Compute the current time, used to figure out server record ages.
399 currTimeP = &currTime;
400 osi_GetuTime(currTimeP);
403 * Sweep the server hash table, tallying all we need to know.
405 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
407 for (currSrvP = afs_servers[currIdx]; currSrvP; currSrvP = currSrvP->next) {
409 * Bump the current chain length.
414 * Any further tallying for this record will only be done if it has
417 if ( (currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED) &&
418 currSrvP->addr && currSrvP->cell ) {
421 * Compute the current server record's age, then remember it
422 * in the appropriate places.
424 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
425 if (currSrvP->addr->sa_portal == AFS_FSPORT) {
426 upDownP = (currSrvP->cell->cell == 1) ?
427 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
428 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
429 } /*File Server record*/
431 upDownP = (currSrvP->cell->cell == 1) ?
432 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
433 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
434 } /*VL Server record*/
436 upDownP->sumOfRecordAges += srvRecordAge;
437 if ((upDownP->ageOfYoungestRecord == 0) ||
438 (srvRecordAge < upDownP->ageOfYoungestRecord))
439 upDownP->ageOfYoungestRecord = srvRecordAge;
440 if ((upDownP->ageOfOldestRecord == 0) ||
441 (srvRecordAge > upDownP->ageOfOldestRecord))
442 upDownP->ageOfOldestRecord = srvRecordAge;
444 if (currSrvP->numDowntimeIncidents <=
445 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
446 (upDownP->downIncidents[0])++;
448 if (currSrvP->numDowntimeIncidents <=
449 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
450 (upDownP->downIncidents[1])++;
452 if (currSrvP->numDowntimeIncidents <=
453 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
454 (upDownP->downIncidents[2])++;
456 if (currSrvP->numDowntimeIncidents <=
457 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
458 (upDownP->downIncidents[3])++;
460 if (currSrvP->numDowntimeIncidents <=
461 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
462 (upDownP->downIncidents[4])++;
464 (upDownP->downIncidents[5])++;
467 } /*Current server has been active*/
468 } /*Walk this chain*/
471 * Before advancing to the next chain, remember facts about this one.
473 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
475 * We beat out the former champion (which was initially set to 0
476 * here). Mark down the new winner, and also remember if it's an
479 afs_stats_cmperf.srvMaxChainLength = currChainLen;
480 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
481 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
482 } /*Update chain length maximum*/
483 } /*For each hash chain*/
486 * We're done. Unlock the server table before returning to our caller.
488 ReleaseReadLock(&afs_xserver);
490 } /*afs_CountServers*/
493 /* check down servers (if adown), or running servers (if !adown) */
494 void afs_CheckServers(adown, acellp)
499 struct vrequest treq;
505 afs_int32 start, end, delta;
511 struct srvAddr **addrs;
514 AFS_STATCNT(afs_CheckServers);
515 if (code = afs_InitReq(&treq, &afs_osi_cred)) return;
516 ObtainReadLock(&afs_xserver); /* Necessary? */
517 ObtainReadLock(&afs_xsrvAddr);
520 for (i=0;i<NSERVERS;i++) {
521 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
526 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
528 for (i=0;i<NSERVERS;i++) {
529 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
530 if (j >= srvAddrCount) break;
535 ReleaseReadLock(&afs_xsrvAddr);
536 ReleaseReadLock(&afs_xserver);
538 for (i=0; i<j; i++) {
544 /* See if a cell to check was specified. If it is spec'd and not
545 * this server's cell, just skip the server.
547 if (acellp && acellp != ts->cell)
550 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN)) ||
551 (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
554 /* check vlserver with special code */
555 if (sa->sa_portal == AFS_VLPORT) {
556 CheckVLServer(sa, &treq);
560 if (!ts->cell) /* not really an active server, anyway, it must */
561 continue; /* have just been added by setsprefs */
563 /* get a connection, even if host is down; bumps conn ref count */
564 tu = afs_GetUser(treq.uid, ts->cell, SHARED_LOCK);
565 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cell, tu,
566 1/*force*/, 1/*create*/, SHARED_LOCK);
567 afs_PutUser(tu, SHARED_LOCK);
570 if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts) ||
571 (tc->srvr->server == afs_setTimeHost)) {
572 if (sa->sa_flags & SRVADDR_ISDOWN) {
573 rx_SetConnDeadTime(tc->id, 3);
579 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME);
580 start = osi_Time(); /* time the gettimeofday call */
582 code = RXAFS_GetTime(tc->id, &tv.tv_sec, &tv.tv_usec);
587 * If we're supposed to set the time, and the call worked
588 * quickly (same second response) and this is the host we
589 * use for the time and the time is really different, then
590 * really set the time
592 if (code == 0 && start == end && afs_setTime != 0 &&
593 (tc->srvr->server == afs_setTimeHost ||
595 * Sync only to a server in the local cell: cell(id)==1
598 (afs_setTimeHost == (struct server *)0 &&
599 (ts->cell->cell == 1 || (ts->cell->states&CPrimary))))) {
601 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
603 delta = end - tv.tv_sec; /* how many secs fast we are */
604 /* see if clock has changed enough to make it worthwhile */
605 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
606 if (delta > AFS_MAXCHANGEBACK) {
607 /* setting clock too far back, just do it a little */
608 tv.tv_sec = end - AFS_MAXCHANGEBACK;
610 afs_osi_SetTime(&tv);
612 strcpy(msgbuf, "afs: setting clock back ");
613 if (delta > AFS_MAXCHANGEBACK) {
614 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], AFS_MAXCHANGEBACK));
615 afs_strcat(msgbuf, " seconds (of ");
616 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta - AFS_MAXCHANGEBACK));
617 afs_strcat(msgbuf, ", via ");
618 print_internet_address(msgbuf, sa, "); clock is still fast.", 0);
620 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta));
621 afs_strcat(msgbuf, " seconds (via ");
622 print_internet_address(msgbuf, sa, ").", 0);
625 strcpy(msgbuf, "afs: setting clock ahead ");
626 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], -delta));
627 afs_strcat(msgbuf, " seconds (via ");
628 print_internet_address(msgbuf, sa, ").", 0);
631 afs_setTimeHost = tc->srvr->server;
634 rx_SetConnDeadTime(tc->id, 50);
635 if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
637 print_internet_address("afs: file server ", sa, " is back up", 2);
639 ObtainWriteLock(&afs_xserver, 244);
640 ObtainWriteLock(&afs_xsrvAddr, 245);
641 afs_MarkServerUpOrDown(sa, 0);
642 ReleaseWriteLock(&afs_xsrvAddr);
643 ReleaseWriteLock(&afs_xserver);
645 if (afs_waitForeverCount) {
646 afs_osi_Wakeup(&afs_waitForever);
652 ForceNewConnections(sa); /* multi homed clients */
657 afs_PutConn(tc, SHARED_LOCK); /* done with it now */
658 } /* Outer loop over addrs */
660 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
662 } /*afs_CheckServers*/
665 /* find a server structure given the host address */
666 struct server *afs_FindServer (afs_int32 aserver, ushort aport,
667 afsUUID *uuidp, afs_int32 locktype)
673 AFS_STATCNT(afs_FindServer);
675 i = afs_uuid_hash(uuidp) % NSERVERS;
676 for (ts = afs_servers[i]; ts; ts = ts->next) {
677 if ( (ts->flags & SRVR_MULTIHOMED) &&
678 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp)) == 0) &&
679 (!ts->addr || (ts->addr->sa_portal == aport)) )
684 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
685 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
690 return (struct server *)0;
695 /* some code for creating new server structs and setting preferences follows
696 * in the next few lines...
699 #define MAXDEFRANK 60000
700 #define DEFRANK 40000
702 /* Random number generator and constants from KnuthV2 2d ed, p170 */
708 a is 0.73m should be 0.01m .. 0.99m
709 c is more or less immaterial. 1 or a is suggested.
711 NB: LOW ORDER BITS are not very random. To get small random numbers,
712 treat result as <1, with implied binary point, and multiply by
714 NB: Has to be unsigned, since shifts on signed quantities may preserve
717 /* added rxi_getaddr() to try to get as much initial randomness as
718 possible, since at least one customer reboots ALL their clients
719 simultaneously -- so osi_Time is bound to be the same on some of the
720 clients. This is probably OK, but I don't want to see too much of it.
723 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
724 extern afs_int32 rxi_getaddr();
726 unsigned int afs_random()
729 static afs_int32 state = 0;
732 AFS_STATCNT(afs_random);
737 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
738 * bits are in a tv_usec
740 state = (t.tv_usec & (~0 << 4) ) + (rxi_getaddr() & 0xff);
741 state += (t.tv_sec & 0xff);
752 /* returns int 0..14 using the high bits of a pseudo-random number instead of
753 the low bits, as the low bits are "less random" than the high ones...
754 slight roundoff error exists, an excercise for the reader.
755 need to multiply by something with lots of ones in it, so multiply by
756 8 or 16 is right out.
758 int afs_randomMod15()
762 temp = afs_random() >> 4;
763 temp = (temp *15) >> 28;
768 int afs_randomMod127()
772 temp = afs_random() >> 7;
773 temp = (temp *127) >> 25;
778 /* afs_SortOneServer()
779 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
781 void afs_SortOneServer(struct server *asp)
783 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
786 for (rootsa=&(asp->addr); *rootsa; rootsa=&(lowsa->next_sa)) {
787 lowprev = (struct srvAddr *)0;
788 lowsa = *rootsa; /* lowest sa is the first one */
789 lowrank = lowsa->sa_iprank;
791 for (tsa=*rootsa; tsa->next_sa; tsa=tsa->next_sa) {
792 rank = tsa->next_sa->sa_iprank;
793 if (rank < lowrank) {
795 lowsa = tsa->next_sa;
796 lowrank = lowsa->sa_iprank;
799 if (lowprev) { /* found one lower, so rearrange them */
800 lowprev->next_sa = lowsa->next_sa;
801 lowsa->next_sa = *rootsa;
808 * Sort the pointer to servers by the server's rank (its lowest rank).
809 * It is assumed that the server already has its IP addrs sorted (the
810 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
812 void afs_SortServers(struct server *aservers[], int count)
817 AFS_STATCNT(afs_SortServers);
819 for (i=0; i<count; i++) {
820 if (!aservers[i]) break;
821 for (low=i,j=i+1; j<=count; j++) {
822 if ((!aservers[j]) || (!aservers[j]->addr))
824 if ((!aservers[low]) || (!aservers[low]->addr))
826 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
832 aservers[i] = aservers[low];
836 } /*afs_SortServers*/
838 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
839 data structures to determine what the local IP addresses and subnet masks
840 are in order to choose which server(s) are on the local subnet.
842 As I see it, there are several cases:
843 1. The server address is one of this host's local addresses. In this case
844 this server is to be preferred over all others.
845 2. The server is on the same subnet as one of the this host's local
846 addresses. (ie, an odd-sized subnet, not class A,B,orC)
847 3. The server is on the same net as this host (class A,B or C)
848 4. The server is on a different logical subnet or net than this host, but
849 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
851 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
853 6. This host and the server are disjoint.
855 That is a rough order of preference. If a point-to-point link has a high
856 metric, I'm assuming that it is a very slow link, and putting it at the
857 bottom of the list (at least until RX works better over slow links). If
858 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
860 It's not easy to check for case #4, so I'm ignoring it for the time being.
862 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
863 That could be used to prefer certain servers fairly easily. Maybe some
866 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
867 protocols (well, addresses that are stored in uint32s, at any rate).
870 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
871 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
873 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
874 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
879 #define PPWEIGHT 4096
884 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
885 #include <inet/common.h>
886 /* IP interface structure, one per local address */
887 typedef struct ipif_s { /**/
888 struct ipif_s * ipif_next;
889 struct ill_s * ipif_ill; /* Back pointer to our ill */
890 long ipif_id; /* Logical unit number */
891 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
892 afs_int32 ipif_local_addr; /* Local IP address for this if. */
893 afs_int32 ipif_net_mask; /* Net mask for this interface. */
894 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
895 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
896 u_int ipif_flags; /* Interface flags. */
897 u_int ipif_metric; /* BSD if metric, for compatibility. */
898 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
899 mblk_t * ipif_arp_down_mp; /* Allocated at time arp comes up to
900 * prevent awkward out of mem condition
903 mblk_t * ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
904 * RESOLVER on this interface so that
905 * they can survive ifconfig down.
908 * The packet counts in the ipif contain the sum of the
909 * packet counts in dead IREs that were affiliated with
912 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
913 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
914 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
916 ipif_multicast_up : 1, /* We have joined the allhosts group */
920 typedef struct ipfb_s { /**/
921 struct ipf_s * ipfb_ipf; /* List of ... */
922 kmutex_t ipfb_lock; /* Protect all ipf in list */
925 typedef struct ilm_s { /**/
928 u_int ilm_timer; /* IGMP */
929 struct ipif_s * ilm_ipif; /* Back pointer to ipif */
930 struct ilm_s * ilm_next; /* Linked list for each ill */
933 typedef struct ill_s { /**/
934 struct ill_s * ill_next; /* Chained in at ill_g_head. */
935 struct ill_s ** ill_ptpn; /* Pointer to previous next. */
936 queue_t * ill_rq; /* Read queue. */
937 queue_t * ill_wq; /* Write queue. */
939 int ill_error; /* Error value sent up by device. */
941 ipif_t * ill_ipif; /* Interface chain for this ILL. */
942 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
943 u_int ill_max_frag; /* Max IDU. */
944 char * ill_name; /* Our name. */
945 u_int ill_name_length; /* Name length, incl. terminator. */
946 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
947 u_int ill_ppa; /* Physical Point of Attachment num. */
949 int ill_sap_length; /* Including sign (for position) */
950 u_int ill_phys_addr_length; /* Excluding the sap. */
951 mblk_t * ill_frag_timer_mp; /* Reassembly timer state. */
952 ipfb_t * ill_frag_hash_tbl; /* Fragment hash list head. */
954 queue_t * ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
955 ipif_t * ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
957 /* ill_hdr_length and ill_hdr_mp will be non zero if
958 * the underlying device supports the M_DATA fastpath
962 ilm_t * ill_ilm; /* Multicast mebership for lower ill */
964 /* All non-nil cells between 'ill_first_mp_to_free' and
965 * 'ill_last_mp_to_free' are freed in ill_delete.
967 #define ill_first_mp_to_free ill_hdr_mp
968 mblk_t * ill_hdr_mp; /* Contains fastpath template */
969 mblk_t * ill_bcast_mp; /* DLPI header for broadcasts. */
970 mblk_t * ill_bind_pending; /* T_BIND_REQ awaiting completion. */
971 mblk_t * ill_resolver_mp; /* Resolver template. */
972 mblk_t * ill_attach_mp;
973 mblk_t * ill_bind_mp;
974 mblk_t * ill_unbind_mp;
975 mblk_t * ill_detach_mp;
976 #define ill_last_mp_to_free ill_detach_mp
979 ill_frag_timer_running : 1,
980 ill_needs_attach : 1,
983 ill_unbind_pending : 1,
985 ill_pad_to_bit_31 : 27;
986 MI_HRT_DCL(ill_rtime)
991 #ifdef AFS_USERSPACE_IP_ADDR
993 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
996 * The IP addresses and ranks are determined by afsd (in user space) and
997 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
998 * system call. These are stored in the data structure
999 * called 'afs_cb_interface'.
1001 afsi_SetServerIPRank(sa, addr, subnetmask)
1002 struct srvAddr *sa; /* remote server */
1003 afs_int32 addr; /* one of my local addr in net order */
1004 afs_uint32 subnetmask; /* subnet mask of local addr in net order */
1006 afs_uint32 myAddr, myNet, mySubnet, netMask;
1007 afs_uint32 serverAddr ;
1009 myAddr = ntohl(addr); /* one of my IP addr in host order */
1010 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1011 subnetmask = ntohl(subnetmask);/* subnet mask in host order */
1013 if ( IN_CLASSA(myAddr) ) netMask = IN_CLASSA_NET;
1014 else if ( IN_CLASSB(myAddr) ) netMask = IN_CLASSB_NET;
1015 else if ( IN_CLASSC(myAddr) ) netMask = IN_CLASSC_NET;
1018 myNet = myAddr & netMask;
1019 mySubnet = myAddr & subnetmask;
1021 if ( (serverAddr & netMask ) == myNet ) {
1022 if ( (serverAddr & subnetmask ) == mySubnet) {
1023 if ( serverAddr == myAddr ) { /* same machine */
1024 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1025 } else { /* same subnet */
1026 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1028 } else { /* same net */
1029 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1033 #else /* AFS_USERSPACE_IP_ADDR */
1034 #if (! defined(AFS_SUN5_ENV)) && defined(USEIFADDR)
1036 afsi_SetServerIPRank(sa, ifa)
1038 struct in_ifaddr *ifa;
1040 struct sockaddr_in *sin;
1043 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1044 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1046 if ( SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1047 sa->sa_iprank = TOPR;
1049 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1050 if (sa->sa_iprank > t)
1054 t = MED + ifa->ia_ifp->if_metric;/* case #3 */
1055 if (sa->sa_iprank > t)
1059 #ifdef IFF_POINTTOPOINT
1060 /* check for case #4 -- point-to-point link */
1061 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT) &&
1062 (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1063 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED)/PPWEIGHT)
1066 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1067 if (sa->sa_iprank > t)
1070 #endif /* IFF_POINTTOPOINT */
1072 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR)*/
1073 #endif /* else AFS_USERSPACE_IP_ADDR */
1075 #ifdef AFS_SGI62_ENV
1077 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1080 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr*)h);
1081 return 0; /* Never match, so we enumerate everyone */
1083 #endif /* AFS_SGI62_ENV */
1085 static afs_SetServerPrefs(sa)
1088 #if defined(AFS_USERSPACE_IP_ADDR)
1089 extern interfaceAddr afs_cb_interface;
1093 for (i=0; i<afs_cb_interface.numberOfInterfaces; i++) {
1094 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1095 afs_cb_interface.subnetmask[i]);
1097 #else /* AFS_USERSPACE_IP_ADDR */
1098 #if defined(AFS_SUN5_ENV)
1099 extern struct ill_s *ill_g_headp;
1102 int subnet, subnetmask, net, netmask;
1103 long *addr = (long *) ill_g_headp;
1104 extern struct ifnet *rxi_FindIfnet();
1106 if (sa) sa->sa_iprank= 0;
1107 for (ill = (struct ill_s *)*addr /*ill_g_headp*/; ill; ill = ill->ill_next ) {
1108 #ifdef AFS_SUN58_ENV
1109 /* Make sure this is an IPv4 ILL */
1110 if (ill->ill_isv6) continue;
1112 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next ) {
1113 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1114 subnetmask = ipif->ipif_net_mask;
1116 * Generate the local net using the local address and
1117 * whate we know about Class A, B and C networks.
1119 if (IN_CLASSA(ipif->ipif_local_addr)) {
1120 netmask = IN_CLASSA_NET;
1121 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1122 netmask = IN_CLASSB_NET;
1123 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1124 netmask = IN_CLASSC_NET;
1128 net = ipif->ipif_local_addr & netmask;
1131 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1133 if (*cnt > 16) return;
1134 *addrp++ = ipif->ipif_local_addr;
1139 /* XXXXXX Do the individual ip ranking below XXXXX */
1140 if ((sa->sa_ip & netmask) == net) {
1141 if ((sa->sa_ip & subnetmask) == subnet) {
1142 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1143 sa->sa_iprank = TOPR;
1145 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1148 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1151 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1153 /* check for case #5 -- point-to-point link */
1154 if ((ipif->ipif_flags & IFF_POINTOPOINT) &&
1155 (ipif->ipif_pp_dst_addr == sa->sa_ip )) {
1157 if (ipif->ipif_metric >= (MAXDEFRANK - MED)/PPWEIGHT)
1158 sa->sa_iprank = MAXDEFRANK;
1160 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1167 struct ifnet *ifn = (struct ifnet *)0;
1168 struct in_ifaddr *ifad = (struct in_ifaddr *) 0;
1169 struct sockaddr_in *sin;
1172 #ifdef notdef /* clean up, remove this */
1173 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1174 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next){
1175 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1176 && !(ifn->if_flags & IFF_LOOPBACK)) {
1178 if (*cnt > 16) return;
1179 *addrp++ = ((struct sockaddr_in *) IFADDR2SA(ifad))->sin_addr.s_addr;
1188 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1190 if (ifn) { /* local, more or less */
1192 if (ifn->if_flags & IFF_LOOPBACK) {
1193 sa->sa_iprank = TOPR;
1196 #endif /* IFF_LOOPBACK */
1197 sin = (struct sockaddr_in *) IA_SIN(ifad);
1198 if (SA2ULONG(sin) == sa->sa_ip) {
1199 sa->sa_iprank = TOPR;
1202 #ifdef IFF_BROADCAST
1203 if (ifn->if_flags & IFF_BROADCAST) {
1204 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1209 #endif /* IFF_BROADCAST */
1210 #ifdef IFF_POINTOPOINT
1211 if (ifn->if_flags & IFF_POINTOPOINT) {
1212 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1213 if (ifn->if_metric > 4) {
1217 else sa->sa_iprank = ifn->if_metric;
1220 #endif /* IFF_POINTOPOINT */
1221 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1224 #else /* USEIFADDR */
1226 if (sa) sa->sa_iprank= LO;
1227 #ifdef AFS_SGI62_ENV
1228 (void) hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1230 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1232 struct in_ifaddr *ifa;
1233 TAILQ_FOREACH(ifa , &in_ifaddrhead, ia_link) {
1234 afsi_SetServerIPRank(sa, ifa);
1239 extern struct in_ifaddr *in_ifaddr;
1240 struct in_ifaddr *ifa;
1241 for ( ifa = in_ifaddr; ifa; ifa = ifa->ia_next ) {
1242 afsi_SetServerIPRank(sa, ifa);
1247 #endif /* USEIFADDR */
1248 #endif /* AFS_SUN5_ENV */
1249 #endif /* else AFS_USERSPACE_IP_ADDR */
1252 if (sa) sa->sa_iprank += afs_randomMod15();
1255 } /* afs_SetServerPrefs */
1262 /* afs_FlushServer()
1263 * The addresses on this server struct has changed in some way and will
1264 * clean up all other structures that may reference it.
1265 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1267 void afs_FlushServer(srvp)
1268 struct server *srvp;
1271 struct server *ts, **pts;
1273 /* Find any volumes residing on this server and flush their state */
1274 afs_ResetVolumes(srvp);
1276 /* Flush all callbacks in the all vcaches for this specific server */
1277 afs_FlushServerCBs(srvp);
1279 /* Remove all the callbacks structs */
1281 struct afs_cbr *cb, *cbnext;
1282 extern afs_lock_t afs_xvcb;
1284 MObtainWriteLock(&afs_xvcb, 300);
1285 for (cb=srvp->cbrs; cb; cb=cbnext) {
1289 srvp->cbrs = (struct afs_cbr *)0;
1290 ReleaseWriteLock(&afs_xvcb);
1293 /* If no more srvAddr structs hanging off of this server struct,
1297 /* Remove the server structure from the cell list - if there */
1298 afs_RemoveCellEntry(srvp);
1300 /* Remove from the afs_servers hash chain */
1301 for (i=0; i<NSERVERS; i++) {
1302 for (pts=&(afs_servers[i]), ts=*pts; ts; pts=&(ts->next), ts=*pts) {
1303 if (ts == srvp) break;
1308 *pts = ts->next; /* Found it. Remove it */
1309 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1315 /* afs_RemoveSrvAddr()
1316 * This removes a SrvAddr structure from its server structure.
1317 * The srvAddr struct is not free'd because it connections may still
1318 * be open to it. It is up to the calling process to make sure it
1319 * remains connected to a server struct.
1320 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1321 * It is not removed from the afs_srvAddrs hash chain.
1323 void afs_RemoveSrvAddr(sap)
1324 struct srvAddr *sap;
1326 struct srvAddr **psa, *sa;
1332 /* Find the srvAddr in the server's list and remove it */
1333 for (psa=&(srv->addr), sa=*psa; sa; psa=&(sa->next_sa), sa=*psa) {
1334 if (sa == sap) break;
1341 /* Flush the server struct since it's IP address has changed */
1342 afs_FlushServer(srv);
1347 * Return an updated and properly initialized server structure
1348 * corresponding to the server ID, cell, and port specified.
1349 * If one does not exist, then one will be created.
1350 * aserver and aport must be in NET byte order.
1352 struct server *afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers,
1353 afs_int32 acell, u_short aport,
1354 afs_int32 locktype, afsUUID *uuidp,
1355 afs_int32 addr_uniquifier)
1357 struct server *oldts=0, *ts, *newts, *orphts=0;
1358 struct srvAddr *oldsa, *sa, *newsa, *nextsa, *orphsa;
1360 afs_int32 iphash, k, srvcount=0;
1361 unsigned int srvhash;
1363 AFS_STATCNT(afs_GetServer);
1365 ObtainSharedLock(&afs_xserver,13);
1367 /* Check if the server struct exists and is up to date */
1369 if (nservers != 1) panic("afs_GetServer: incorect count of servers");
1370 ObtainReadLock(&afs_xsrvAddr);
1371 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1372 ReleaseReadLock(&afs_xsrvAddr);
1373 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1374 /* Found a server struct that is not multihomed and has the
1375 * IP address associated with it. A correct match.
1377 ReleaseSharedLock(&afs_xserver);
1381 if (nservers <= 0) panic("afs_GetServer: incorrect count of servers");
1382 ts = afs_FindServer(0, aport, uuidp, locktype);
1383 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1384 /* Found a server struct that is multihomed and same
1385 * uniqufier (same IP addrs). The above if statement is the
1386 * same as in InstallUVolumeEntry().
1388 ReleaseSharedLock(&afs_xserver);
1391 if (ts) oldts = ts; /* Will reuse if same uuid */
1394 UpgradeSToWLock(&afs_xserver,36);
1395 ObtainWriteLock(&afs_xsrvAddr,116);
1397 srvcount = afs_totalServers;
1399 /* Reuse/allocate a new server structure */
1403 newts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1404 if (!newts) panic("malloc of server struct");
1406 memset((char *)newts, 0, sizeof(struct server));
1408 /* Add the server struct to the afs_servers[] hash chain */
1409 srvhash = (uuidp ? (afs_uuid_hash(uuidp)%NSERVERS) : SHash(aserverp[0]));
1410 newts->next = afs_servers[srvhash];
1411 afs_servers[srvhash] = newts;
1414 /* Initialize the server structure */
1415 if (uuidp) { /* Multihomed */
1416 newts->sr_uuid = *uuidp;
1417 newts->sr_addr_uniquifier = addr_uniquifier;
1418 newts->flags |= SRVR_MULTIHOMED;
1420 if (acell) newts->cell = afs_GetCell(acell, 0);
1422 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1424 /* For each IP address we are registering */
1425 for (k=0; k<nservers; k++) {
1426 iphash = SHash(aserverp[k]);
1428 /* Check if the srvAddr structure already exists. If so, remove
1429 * it from its server structure and add it to the new one.
1431 for (oldsa=afs_srvAddrs[iphash]; oldsa; oldsa=oldsa->next_bkt) {
1432 if ( (oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport) ) break;
1434 if (oldsa && (oldsa->server != newts)) {
1435 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1436 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1437 newts->addr = oldsa;
1440 /* Reuse/allocate a new srvAddr structure */
1444 newsa = (struct srvAddr *) afs_osi_Alloc(sizeof(struct srvAddr));
1445 if (!newsa) panic("malloc of srvAddr struct");
1446 afs_totalSrvAddrs++;
1447 memset((char *)newsa, 0, sizeof(struct srvAddr));
1449 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1450 newsa->next_bkt = afs_srvAddrs[iphash];
1451 afs_srvAddrs[iphash] = newsa;
1453 /* Hang off of the server structure */
1454 newsa->next_sa = newts->addr;
1455 newts->addr = newsa;
1457 /* Initialize the srvAddr Structure */
1458 newsa->sa_ip = aserverp[k];
1459 newsa->sa_portal = aport;
1462 /* Update the srvAddr Structure */
1463 newsa->server = newts;
1464 if (newts->flags & SRVR_ISDOWN)
1465 newsa->sa_flags |= SRVADDR_ISDOWN;
1466 if (uuidp) newsa->sa_flags |= SRVADDR_MH;
1467 else newsa->sa_flags &= ~SRVADDR_MH;
1469 /* Compute preference values and resort */
1470 if (!newsa->sa_iprank) {
1471 if (aport == fsport) {
1472 afs_SetServerPrefs(newsa); /* new fileserver rank */
1474 newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
1478 afs_SortOneServer(newts); /* Sort by rank */
1480 /* If we reused the server struct, remove any of its srvAddr
1481 * structs that will no longer be associated with this server.
1483 if (oldts) { /* reused the server struct */
1484 for (orphsa=newts->addr; orphsa; orphsa=nextsa) {
1485 nextsa = orphsa->next_sa;
1486 for (k=0; k<nservers; k++) {
1487 if (orphsa->sa_ip == aserverp[k]) break; /* belongs */
1489 if (k < nservers) continue; /* belongs */
1491 /* Have a srvAddr struct. Now get a server struct (if not already) */
1493 orphts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1494 if (!orphts) panic("malloc of lo server struct");
1495 memset((char *)orphts, 0, sizeof(struct server));
1498 /* Add the orphaned server to the afs_servers[] hash chain.
1499 * Its iphash does not matter since we never look up the server
1500 * in the afs_servers table by its ip address (only by uuid -
1501 * which this has none).
1503 iphash = SHash(aserverp[k]);
1504 orphts->next = afs_servers[iphash];
1505 afs_servers[iphash] = orphts;
1507 if (acell) orphts->cell = afs_GetCell(acell, 0);
1510 /* Hang the srvAddr struct off of the server structure. The server
1511 * may have multiple srvAddrs, but it won't be marked multihomed.
1513 afs_RemoveSrvAddr(orphsa); /* remove */
1514 orphsa->next_sa = orphts->addr; /* hang off server struct */
1515 orphts->addr = orphsa;
1516 orphsa->server = orphts;
1517 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1518 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1522 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1524 struct afs_stats_SrvUpDownInfo *upDownP;
1525 /* With the introduction of this new record, we need to adjust the
1526 * proper individual & global server up/down info.
1528 if (aport == fsport) { /* File Server record */
1529 upDownP = (acell == 1) ?
1530 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1531 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1532 } else { /* VL Server record */
1533 upDownP = (acell == 1) ?
1534 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1535 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1537 (upDownP->numTtlRecords) += srvcount;
1538 afs_stats_cmperf.srvRecords += srvcount;
1539 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1540 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1543 ReleaseWriteLock(&afs_xsrvAddr);
1544 ReleaseWriteLock(&afs_xserver);
1546 } /* afs_GetServer */
1548 void afs_ActivateServer(sap)
1549 struct srvAddr *sap;
1551 osi_timeval_t currTime; /*Filled with current time*/
1552 osi_timeval_t *currTimeP; /*Ptr to above*/
1553 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
1554 struct server *aserver = sap->server;
1556 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1558 * This server record has not yet been activated. Go for it,
1559 * recording its ``birth''.
1561 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1562 currTimeP = &currTime;
1563 osi_GetuTime(currTimeP);
1564 aserver->activationTime = currTime.tv_sec;
1565 if (sap->sa_portal == AFS_FSPORT) {
1566 upDownP = (aserver->cell->cell == 1) ?
1567 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1568 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1569 } /*File Server record*/
1571 upDownP = (aserver->cell->cell == 1) ?
1572 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1573 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1574 } /*VL Server record*/
1575 if (aserver->flags & SRVR_ISDOWN)
1576 (upDownP->numDownRecords)++;
1578 (upDownP->numUpRecords)++;
1579 (upDownP->numRecordsNeverDown)++;