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 "../afs/param.h" /* Should be always first */
33 #include <afsconfig.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);
300 #ifdef RX_ENABLE_LOCKS
302 #endif /* RX_ENABLE_LOCKS */
303 code = VL_ProbeServer(tc->id);
304 #ifdef RX_ENABLE_LOCKS
306 #endif /* RX_ENABLE_LOCKS */
307 rx_SetConnDeadTime(tc->id, 50);
308 afs_PutConn(tc, SHARED_LOCK);
310 * If probe worked, or probe call not yet defined (for compatibility
311 * with old vlsevers), then we treat this server as running again
313 if (code == 0 || (code <= -450 && code >= -470)) {
314 if (tc->srvr == sa) {
315 afs_MarkServerUpOrDown(sa, 0);
316 print_internet_address("afs: volume location server ",
317 sa, " is back up", 2);
324 #ifndef AFS_MINCHANGE /* So that some can increase it in param.h */
325 #define AFS_MINCHANGE 2 /* min change we'll bother with */
327 #ifndef AFS_MAXCHANGEBACK
328 #define AFS_MAXCHANGEBACK 10 /* max seconds we'll set a clock back at once */
332 /*------------------------------------------------------------------------
333 * EXPORTED afs_CountServers
336 * Originally meant to count the number of servers and determining
337 * up/down info, this routine will now simply sum up all of the
338 * server record ages. All other up/down information is kept on the
348 * This routine locks afs_xserver for write for the duration.
351 * Set CM perf stats field sumOfRecordAges for all server record
353 *------------------------------------------------------------------------*/
355 void afs_CountServers()
357 { /*afs_CountServers*/
359 int currIdx; /*Curr idx into srv table*/
360 struct server *currSrvP; /*Ptr to curr server record*/
361 afs_int32 currChainLen; /*Length of curr hash chain*/
362 osi_timeval_t currTime; /*Current time*/
363 osi_timeval_t *currTimeP; /*Ptr to above*/
364 afs_int32 srvRecordAge; /*Age of server record, in secs*/
365 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to current up/down
366 info being manipulated*/
369 * Write-lock the server table so we don't get any interference.
371 ObtainReadLock(&afs_xserver);
374 * Iterate over each hash index in the server table, walking down each
375 * chain and tallying what we haven't computed from the records there on
376 * the fly. First, though, initialize the tallies that will change.
378 afs_stats_cmperf.srvMaxChainLength = 0;
380 afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
381 afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
382 afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
383 bzero((char *) afs_stats_cmperf.fs_UpDown[0].downIncidents,
384 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
386 afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
387 afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
388 afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
389 bzero((char *) afs_stats_cmperf.fs_UpDown[1].downIncidents,
390 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
392 afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
393 afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
394 afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
395 bzero((char *) afs_stats_cmperf.vl_UpDown[0].downIncidents,
396 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
398 afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
399 afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
400 afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
401 bzero((char *) afs_stats_cmperf.vl_UpDown[1].downIncidents,
402 AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
405 * Compute the current time, used to figure out server record ages.
407 currTimeP = &currTime;
408 osi_GetuTime(currTimeP);
411 * Sweep the server hash table, tallying all we need to know.
413 for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
415 for (currSrvP = afs_servers[currIdx]; currSrvP; currSrvP = currSrvP->next) {
417 * Bump the current chain length.
422 * Any further tallying for this record will only be done if it has
425 if ( (currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED) &&
426 currSrvP->addr && currSrvP->cell ) {
429 * Compute the current server record's age, then remember it
430 * in the appropriate places.
432 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
433 if (currSrvP->addr->sa_portal == AFS_FSPORT) {
434 upDownP = (currSrvP->cell->cell == 1) ?
435 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
436 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
437 } /*File Server record*/
439 upDownP = (currSrvP->cell->cell == 1) ?
440 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
441 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
442 } /*VL Server record*/
444 upDownP->sumOfRecordAges += srvRecordAge;
445 if ((upDownP->ageOfYoungestRecord == 0) ||
446 (srvRecordAge < upDownP->ageOfYoungestRecord))
447 upDownP->ageOfYoungestRecord = srvRecordAge;
448 if ((upDownP->ageOfOldestRecord == 0) ||
449 (srvRecordAge > upDownP->ageOfOldestRecord))
450 upDownP->ageOfOldestRecord = srvRecordAge;
452 if (currSrvP->numDowntimeIncidents <=
453 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
454 (upDownP->downIncidents[0])++;
456 if (currSrvP->numDowntimeIncidents <=
457 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
458 (upDownP->downIncidents[1])++;
460 if (currSrvP->numDowntimeIncidents <=
461 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
462 (upDownP->downIncidents[2])++;
464 if (currSrvP->numDowntimeIncidents <=
465 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
466 (upDownP->downIncidents[3])++;
468 if (currSrvP->numDowntimeIncidents <=
469 AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
470 (upDownP->downIncidents[4])++;
472 (upDownP->downIncidents[5])++;
475 } /*Current server has been active*/
476 } /*Walk this chain*/
479 * Before advancing to the next chain, remember facts about this one.
481 if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
483 * We beat out the former champion (which was initially set to 0
484 * here). Mark down the new winner, and also remember if it's an
487 afs_stats_cmperf.srvMaxChainLength = currChainLen;
488 if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
489 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
490 } /*Update chain length maximum*/
491 } /*For each hash chain*/
494 * We're done. Unlock the server table before returning to our caller.
496 ReleaseReadLock(&afs_xserver);
498 } /*afs_CountServers*/
501 /* check down servers (if adown), or running servers (if !adown) */
502 void afs_CheckServers(adown, acellp)
507 struct vrequest treq;
513 afs_int32 start, end, delta;
520 AFS_STATCNT(afs_CheckServers);
521 if (code = afs_InitReq(&treq, &afs_osi_cred)) return;
522 ObtainReadLock(&afs_xserver); /* Necessary? */
523 ObtainReadLock(&afs_xsrvAddr);
525 for (i=0;i<NSERVERS;i++) {
526 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
530 /* See if a cell to check was specified. If it is spec'd and not
531 * this server's cell, just skip the server.
533 if (acellp && acellp != ts->cell)
536 if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
537 || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
539 /* check vlserver with special code */
540 if (sa->sa_portal == AFS_VLPORT) {
541 CheckVLServer(sa, &treq);
545 if (!ts->cell) /* not really an active server, anyway, it must */
546 continue; /* have just been added by setsprefs */
548 /* get a connection, even if host is down; bumps conn ref count */
549 tu = afs_GetUser(treq.uid, ts->cell, SHARED_LOCK);
550 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cell, tu,
551 1/*force*/, 1/*create*/, SHARED_LOCK);
552 afs_PutUser(tu, SHARED_LOCK);
556 if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts) ||
557 (tc->srvr->server == afs_setTimeHost)) {
558 if (sa->sa_flags & SRVADDR_ISDOWN) {
559 rx_SetConnDeadTime(tc->id, 3);
563 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETTIME);
564 start = osi_Time(); /* time the gettimeofday call */
565 #ifdef RX_ENABLE_LOCKS
567 #endif /* RX_ENABLE_LOCKS */
568 code = RXAFS_GetTime(tc->id, &tv.tv_sec, &tv.tv_usec);
569 #ifdef RX_ENABLE_LOCKS
571 #endif /* RX_ENABLE_LOCKS */
575 * If we're supposed to set the time, and the call worked
576 * quickly (same second response) and this is the host we
577 * use for the time and the time is really different, then
578 * really set the time
580 if (code == 0 && start == end && afs_setTime != 0 &&
581 (tc->srvr->server == afs_setTimeHost ||
583 * Sync only to a server in the local cell: cell(id)==1
586 (afs_setTimeHost == (struct server *)0 &&
587 (ts->cell->cell == 1 || (ts->cell->states&CPrimary))))) {
588 char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
590 delta = end - tv.tv_sec; /* how many secs fast we are */
591 /* see if clock has changed enough to make it worthwhile */
592 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
593 if (delta > AFS_MAXCHANGEBACK) {
594 /* setting clock too far back, just do it a little */
595 tv.tv_sec = end - AFS_MAXCHANGEBACK;
597 afs_osi_SetTime(&tv);
599 strcpy(msgbuf, "afs: setting clock back ");
600 if (delta > AFS_MAXCHANGEBACK) {
601 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], AFS_MAXCHANGEBACK));
602 afs_strcat(msgbuf, " seconds (of ");
603 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta - AFS_MAXCHANGEBACK));
604 afs_strcat(msgbuf, ", via ");
605 print_internet_address(msgbuf, sa, "); clock is still fast.", 0);
607 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], delta));
608 afs_strcat(msgbuf, " seconds (via ");
609 print_internet_address(msgbuf, sa, ").", 0);
613 strcpy(msgbuf, "afs: setting clock ahead ");
614 afs_strcat(msgbuf, afs_cv2string(&tbuffer[CVBS], -delta));
615 afs_strcat(msgbuf, " seconds (via ");
616 print_internet_address(msgbuf, sa, ").", 0);
619 afs_setTimeHost = tc->srvr->server;
622 rx_SetConnDeadTime(tc->id, 50);
623 if (code >= 0 && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
625 print_internet_address("afs: file server ", sa, " is back up", 2);
627 * XXX We should hold a server write lock here XXX
629 afs_MarkServerUpOrDown(sa, 0);
630 if (afs_waitForeverCount) {
631 afs_osi_Wakeup(&afs_waitForever);
638 ForceNewConnections(sa); /* multi homed clients */
642 afs_PutConn(tc, SHARED_LOCK); /* done with it now */
643 } /* for each server loop */
644 } /* for each server hash bucket loop */
645 ReleaseReadLock(&afs_xsrvAddr);
646 ReleaseReadLock(&afs_xserver);
648 } /*afs_CheckServers*/
651 /* find a server structure given the host address */
652 struct server *afs_FindServer (afs_int32 aserver, ushort aport,
653 afsUUID *uuidp, afs_int32 locktype)
659 AFS_STATCNT(afs_FindServer);
661 i = afs_uuid_hash(uuidp) % NSERVERS;
662 for (ts = afs_servers[i]; ts; ts = ts->next) {
663 if ( (ts->flags & SRVR_MULTIHOMED) &&
664 (bcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp)) == 0) &&
665 (!ts->addr || (ts->addr->sa_portal == aport)) )
670 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
671 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
676 return (struct server *)0;
681 /* some code for creating new server structs and setting preferences follows
682 * in the next few lines...
685 #define MAXDEFRANK 60000
686 #define DEFRANK 40000
688 /* Random number generator and constants from KnuthV2 2d ed, p170 */
694 a is 0.73m should be 0.01m .. 0.99m
695 c is more or less immaterial. 1 or a is suggested.
697 NB: LOW ORDER BITS are not very random. To get small random numbers,
698 treat result as <1, with implied binary point, and multiply by
700 NB: Has to be unsigned, since shifts on signed quantities may preserve
703 /* added rxi_getaddr() to try to get as much initial randomness as
704 possible, since at least one customer reboots ALL their clients
705 simultaneously -- so osi_Time is bound to be the same on some of the
706 clients. This is probably OK, but I don't want to see too much of it.
709 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
710 extern afs_int32 rxi_getaddr();
712 unsigned int afs_random()
715 static afs_int32 state = 0;
718 AFS_STATCNT(afs_random);
723 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
724 * bits are in a tv_usec
726 state = (t.tv_usec & (~0 << 4) ) + (rxi_getaddr() & 0xff);
727 state += (t.tv_sec & 0xff);
738 /* returns int 0..14 using the high bits of a pseudo-random number instead of
739 the low bits, as the low bits are "less random" than the high ones...
740 slight roundoff error exists, an excercise for the reader.
741 need to multiply by something with lots of ones in it, so multiply by
742 8 or 16 is right out.
744 int afs_randomMod15()
748 temp = afs_random() >> 4;
749 temp = (temp *15) >> 28;
754 int afs_randomMod127()
758 temp = afs_random() >> 7;
759 temp = (temp *127) >> 25;
764 /* afs_SortOneServer()
765 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
767 void afs_SortOneServer(struct server *asp)
769 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
772 for (rootsa=&(asp->addr); *rootsa; rootsa=&(lowsa->next_sa)) {
773 lowprev = (struct srvAddr *)0;
774 lowsa = *rootsa; /* lowest sa is the first one */
775 lowrank = lowsa->sa_iprank;
777 for (tsa=*rootsa; tsa->next_sa; tsa=tsa->next_sa) {
778 rank = tsa->next_sa->sa_iprank;
779 if (rank < lowrank) {
781 lowsa = tsa->next_sa;
782 lowrank = lowsa->sa_iprank;
785 if (lowprev) { /* found one lower, so rearrange them */
786 lowprev->next_sa = lowsa->next_sa;
787 lowsa->next_sa = *rootsa;
794 * Sort the pointer to servers by the server's rank (its lowest rank).
795 * It is assumed that the server already has its IP addrs sorted (the
796 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
798 void afs_SortServers(struct server *aservers[], int count)
803 AFS_STATCNT(afs_SortServers);
805 for (i=0; i<count; i++) {
806 if (!aservers[i]) break;
807 for (low=i,j=i+1; j<=count; j++) {
808 if (!aservers[j]) break;
809 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
815 aservers[i] = aservers[low];
819 } /*afs_SortServers*/
821 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
822 data structures to determine what the local IP addresses and subnet masks
823 are in order to choose which server(s) are on the local subnet.
825 As I see it, there are several cases:
826 1. The server address is one of this host's local addresses. In this case
827 this server is to be preferred over all others.
828 2. The server is on the same subnet as one of the this host's local
829 addresses. (ie, an odd-sized subnet, not class A,B,orC)
830 3. The server is on the same net as this host (class A,B or C)
831 4. The server is on a different logical subnet or net than this host, but
832 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
834 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
836 6. This host and the server are disjoint.
838 That is a rough order of preference. If a point-to-point link has a high
839 metric, I'm assuming that it is a very slow link, and putting it at the
840 bottom of the list (at least until RX works better over slow links). If
841 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
843 It's not easy to check for case #4, so I'm ignoring it for the time being.
845 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
846 That could be used to prefer certain servers fairly easily. Maybe some
849 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
850 protocols (well, addresses that are stored in uint32s, at any rate).
853 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
854 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
856 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
857 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
862 #define PPWEIGHT 4096
867 #if defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
868 #include <inet/common.h>
869 /* IP interface structure, one per local address */
870 typedef struct ipif_s { /**/
871 struct ipif_s * ipif_next;
872 struct ill_s * ipif_ill; /* Back pointer to our ill */
873 long ipif_id; /* Logical unit number */
874 u_int ipif_mtu; /* Starts at ipif_ill->ill_max_frag */
875 afs_int32 ipif_local_addr; /* Local IP address for this if. */
876 afs_int32 ipif_net_mask; /* Net mask for this interface. */
877 afs_int32 ipif_broadcast_addr; /* Broadcast addr for this interface. */
878 afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
879 u_int ipif_flags; /* Interface flags. */
880 u_int ipif_metric; /* BSD if metric, for compatibility. */
881 u_int ipif_ire_type; /* LOCAL or LOOPBACK */
882 mblk_t * ipif_arp_down_mp; /* Allocated at time arp comes up to
883 * prevent awkward out of mem condition
886 mblk_t * ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
887 * RESOLVER on this interface so that
888 * they can survive ifconfig down.
891 * The packet counts in the ipif contain the sum of the
892 * packet counts in dead IREs that were affiliated with
895 u_long ipif_fo_pkt_count; /* Forwarded thru our dead IREs */
896 u_long ipif_ib_pkt_count; /* Inbound packets for our dead IREs */
897 u_long ipif_ob_pkt_count; /* Outbound packets to our dead IREs */
899 ipif_multicast_up : 1, /* We have joined the allhosts group */
903 typedef struct ipfb_s { /**/
904 struct ipf_s * ipfb_ipf; /* List of ... */
905 kmutex_t ipfb_lock; /* Protect all ipf in list */
908 typedef struct ilm_s { /**/
911 u_int ilm_timer; /* IGMP */
912 struct ipif_s * ilm_ipif; /* Back pointer to ipif */
913 struct ilm_s * ilm_next; /* Linked list for each ill */
916 typedef struct ill_s { /**/
917 struct ill_s * ill_next; /* Chained in at ill_g_head. */
918 struct ill_s ** ill_ptpn; /* Pointer to previous next. */
919 queue_t * ill_rq; /* Read queue. */
920 queue_t * ill_wq; /* Write queue. */
922 int ill_error; /* Error value sent up by device. */
924 ipif_t * ill_ipif; /* Interface chain for this ILL. */
925 u_int ill_ipif_up_count; /* Number of IPIFs currently up. */
926 u_int ill_max_frag; /* Max IDU. */
927 char * ill_name; /* Our name. */
928 u_int ill_name_length; /* Name length, incl. terminator. */
929 u_int ill_subnet_type; /* IRE_RESOLVER or IRE_SUBNET. */
930 u_int ill_ppa; /* Physical Point of Attachment num. */
932 int ill_sap_length; /* Including sign (for position) */
933 u_int ill_phys_addr_length; /* Excluding the sap. */
934 mblk_t * ill_frag_timer_mp; /* Reassembly timer state. */
935 ipfb_t * ill_frag_hash_tbl; /* Fragment hash list head. */
937 queue_t * ill_bind_pending_q; /* Queue waiting for DL_BIND_ACK. */
938 ipif_t * ill_ipif_pending; /* IPIF waiting for DL_BIND_ACK. */
940 /* ill_hdr_length and ill_hdr_mp will be non zero if
941 * the underlying device supports the M_DATA fastpath
945 ilm_t * ill_ilm; /* Multicast mebership for lower ill */
947 /* All non-nil cells between 'ill_first_mp_to_free' and
948 * 'ill_last_mp_to_free' are freed in ill_delete.
950 #define ill_first_mp_to_free ill_hdr_mp
951 mblk_t * ill_hdr_mp; /* Contains fastpath template */
952 mblk_t * ill_bcast_mp; /* DLPI header for broadcasts. */
953 mblk_t * ill_bind_pending; /* T_BIND_REQ awaiting completion. */
954 mblk_t * ill_resolver_mp; /* Resolver template. */
955 mblk_t * ill_attach_mp;
956 mblk_t * ill_bind_mp;
957 mblk_t * ill_unbind_mp;
958 mblk_t * ill_detach_mp;
959 #define ill_last_mp_to_free ill_detach_mp
962 ill_frag_timer_running : 1,
963 ill_needs_attach : 1,
966 ill_unbind_pending : 1,
968 ill_pad_to_bit_31 : 27;
969 MI_HRT_DCL(ill_rtime)
974 #ifdef AFS_USERSPACE_IP_ADDR
976 #define min(A,B) ((A)<(B)) ? (A) : (B)
979 * The IP addresses and ranks are determined by afsd (in user space) and
980 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
981 * system call. These are stored in the data structure
982 * called 'afs_cb_interface'.
984 afsi_SetServerIPRank(sa, addr, subnetmask)
985 struct srvAddr *sa; /* remote server */
986 afs_int32 addr; /* one of my local addr in net order */
987 afs_uint32 subnetmask; /* subnet mask of local addr in net order */
989 afs_uint32 myAddr, myNet, mySubnet, netMask;
990 afs_uint32 serverAddr ;
992 myAddr = ntohl(addr); /* one of my IP addr in host order */
993 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
994 subnetmask = ntohl(subnetmask);/* subnet mask in host order */
996 if ( IN_CLASSA(myAddr) ) netMask = IN_CLASSA_NET;
997 else if ( IN_CLASSB(myAddr) ) netMask = IN_CLASSB_NET;
998 else if ( IN_CLASSC(myAddr) ) netMask = IN_CLASSC_NET;
1001 myNet = myAddr & netMask;
1002 mySubnet = myAddr & subnetmask;
1004 if ( (serverAddr & netMask ) == myNet ) {
1005 if ( (serverAddr & subnetmask ) == mySubnet) {
1006 if ( serverAddr == myAddr ) { /* same machine */
1007 sa->sa_iprank = min(sa->sa_iprank, TOPR);
1008 } else { /* same subnet */
1009 sa->sa_iprank = min(sa->sa_iprank, HI);
1011 } else { /* same net */
1012 sa->sa_iprank = min(sa->sa_iprank, MED);
1016 #else /* AFS_USERSPACE_IP_ADDR */
1017 #if (! defined(AFS_SUN5_ENV)) && defined(USEIFADDR)
1019 afsi_SetServerIPRank(sa, ifa)
1021 struct in_ifaddr *ifa;
1023 struct sockaddr_in *sin;
1026 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1027 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1029 if ( SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1030 sa->sa_iprank = TOPR;
1032 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1033 if (sa->sa_iprank > t)
1037 t = MED + ifa->ia_ifp->if_metric;/* case #3 */
1038 if (sa->sa_iprank > t)
1042 #ifdef IFF_POINTTOPOINT
1043 /* check for case #4 -- point-to-point link */
1044 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT) &&
1045 (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1046 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED)/PPWEIGHT)
1049 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1050 if (sa->sa_iprank > t)
1053 #endif /* IFF_POINTTOPOINT */
1055 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR)*/
1056 #endif /* else AFS_USERSPACE_IP_ADDR */
1058 #ifdef AFS_SGI62_ENV
1060 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1063 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr*)h);
1064 return 0; /* Never match, so we enumerate everyone */
1066 #endif /* AFS_SGI62_ENV */
1068 static afs_SetServerPrefs(sa)
1071 #if defined(AFS_USERSPACE_IP_ADDR)
1072 extern interfaceAddr afs_cb_interface;
1076 for (i=0; i<afs_cb_interface.numberOfInterfaces; i++) {
1077 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1078 afs_cb_interface.subnetmask[i]);
1080 #else /* AFS_USERSPACE_IP_ADDR */
1081 #if defined(AFS_SUN5_ENV)
1082 extern struct ill_s *ill_g_headp;
1085 int subnet, subnetmask, net, netmask;
1086 long *addr = (long *) ill_g_headp;
1087 extern struct ifnet *rxi_FindIfnet();
1089 if (sa) sa->sa_iprank= 0;
1090 for (ill = (struct ill_s *)*addr /*ill_g_headp*/; ill; ill = ill->ill_next ) {
1091 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next ) {
1092 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1093 subnetmask = ipif->ipif_net_mask;
1095 * Generate the local net using the local address and
1096 * whate we know about Class A, B and C networks.
1098 if (IN_CLASSA(ipif->ipif_local_addr)) {
1099 netmask = IN_CLASSA_NET;
1100 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1101 netmask = IN_CLASSB_NET;
1102 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1103 netmask = IN_CLASSC_NET;
1107 net = ipif->ipif_local_addr & netmask;
1110 if (ipif->ipif_local_addr != 0x7f000001) { /* ignore loopback */
1112 if (*cnt > 16) return;
1113 *addrp++ = ipif->ipif_local_addr;
1118 /* XXXXXX Do the individual ip ranking below XXXXX */
1119 if ((sa->sa_ip & netmask) == net) {
1120 if ((sa->sa_ip & subnetmask) == subnet) {
1121 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1122 sa->sa_iprank = TOPR;
1124 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1127 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1130 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1132 /* check for case #5 -- point-to-point link */
1133 if ((ipif->ipif_flags & IFF_POINTOPOINT) &&
1134 (ipif->ipif_pp_dst_addr == sa->sa_ip )) {
1136 if (ipif->ipif_metric >= (MAXDEFRANK - MED)/PPWEIGHT)
1137 sa->sa_iprank = MAXDEFRANK;
1139 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1146 struct ifnet *ifn = (struct ifnet *)0;
1147 struct in_ifaddr *ifad = (struct in_ifaddr *) 0;
1148 struct sockaddr_in *sin;
1151 #ifdef notdef /* clean up, remove this */
1152 for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1153 for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next){
1154 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1155 && !(ifn->if_flags & IFF_LOOPBACK)) {
1157 if (*cnt > 16) return;
1158 *addrp++ = ((struct sockaddr_in *) IFADDR2SA(ifad))->sin_addr.s_addr;
1167 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1169 if (ifn) { /* local, more or less */
1171 if (ifn->if_flags & IFF_LOOPBACK) {
1172 sa->sa_iprank = TOPR;
1175 #endif /* IFF_LOOPBACK */
1176 sin = (struct sockaddr_in *) IA_SIN(ifad);
1177 if (SA2ULONG(sin) == sa->sa_ip) {
1178 sa->sa_iprank = TOPR;
1181 #ifdef IFF_BROADCAST
1182 if (ifn->if_flags & IFF_BROADCAST) {
1183 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1188 #endif /* IFF_BROADCAST */
1189 #ifdef IFF_POINTOPOINT
1190 if (ifn->if_flags & IFF_POINTOPOINT) {
1191 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1192 if (ifn->if_metric > 4) {
1196 else sa->sa_iprank = ifn->if_metric;
1199 #endif /* IFF_POINTOPOINT */
1200 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1203 #else /* USEIFADDR */
1205 if (sa) sa->sa_iprank= LO;
1206 #ifdef AFS_SGI62_ENV
1207 (void) hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1209 #elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1211 struct in_ifaddr *ifa;
1212 TAILQ_FOREACH(ifa , &in_ifaddrhead, ia_link) {
1213 afsi_SetServerIPRank(sa, ifa);
1218 extern struct in_ifaddr *in_ifaddr;
1219 struct in_ifaddr *ifa;
1220 for ( ifa = in_ifaddr; ifa; ifa = ifa->ia_next ) {
1221 afsi_SetServerIPRank(sa, ifa);
1226 #endif /* USEIFADDR */
1227 #endif /* AFS_SUN5_ENV */
1228 #endif /* else AFS_USERSPACE_IP_ADDR */
1231 if (sa) sa->sa_iprank += afs_randomMod15();
1234 } /* afs_SetServerPrefs */
1241 /* afs_FlushServer()
1242 * The addresses on this server struct has changed in some way and will
1243 * clean up all other structures that may reference it.
1244 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1246 void afs_FlushServer(srvp)
1247 struct server *srvp;
1250 struct server *ts, **pts;
1252 /* Find any volumes residing on this server and flush their state */
1253 afs_ResetVolumes(srvp);
1255 /* Flush all callbacks in the all vcaches for this specific server */
1256 afs_FlushServerCBs(srvp);
1258 /* Remove all the callbacks structs */
1260 struct afs_cbr *cb, *cbnext;
1261 extern afs_lock_t afs_xvcb;
1263 MObtainWriteLock(&afs_xvcb, 300);
1264 for (cb=srvp->cbrs; cb; cb=cbnext) {
1268 srvp->cbrs = (struct afs_cbr *)0;
1269 ReleaseWriteLock(&afs_xvcb);
1272 /* If no more srvAddr structs hanging off of this server struct,
1276 /* Remove the server structure from the cell list - if there */
1277 afs_RemoveCellEntry(srvp);
1279 /* Remove from the afs_servers hash chain */
1280 for (i=0; i<NSERVERS; i++) {
1281 for (pts=&(afs_servers[i]), ts=*pts; ts; pts=&(ts->next), ts=*pts) {
1282 if (ts == srvp) break;
1287 *pts = ts->next; /* Found it. Remove it */
1288 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1294 /* afs_RemoveSrvAddr()
1295 * This removes a SrvAddr structure from its server structure.
1296 * The srvAddr struct is not free'd because it connections may still
1297 * be open to it. It is up to the calling process to make sure it
1298 * remains connected to a server struct.
1299 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1300 * It is not removed from the afs_srvAddrs hash chain.
1302 void afs_RemoveSrvAddr(sap)
1303 struct srvAddr *sap;
1305 struct srvAddr **psa, *sa;
1311 /* Find the srvAddr in the server's list and remove it */
1312 for (psa=&(srv->addr), sa=*psa; sa; psa=&(sa->next_sa), sa=*psa) {
1313 if (sa == sap) break;
1320 /* Flush the server struct since it's IP address has changed */
1321 afs_FlushServer(srv);
1326 * Return an updated and properly initialized server structure
1327 * corresponding to the server ID, cell, and port specified.
1328 * If one does not exist, then one will be created.
1329 * aserver and aport must be in NET byte order.
1331 struct server *afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers,
1332 afs_int32 acell, u_short aport,
1333 afs_int32 locktype, afsUUID *uuidp,
1334 afs_int32 addr_uniquifier)
1336 struct server *oldts=0, *ts, *newts, *orphts=0;
1337 struct srvAddr *oldsa, *sa, *newsa, *nextsa, *orphsa;
1339 afs_int32 iphash, k, srvcount=0;
1340 unsigned int srvhash;
1342 AFS_STATCNT(afs_GetServer);
1344 ObtainSharedLock(&afs_xserver,13);
1346 /* Check if the server struct exists and is up to date */
1348 if (nservers != 1) panic("afs_GetServer: incorect count of servers");
1349 ObtainReadLock(&afs_xsrvAddr);
1350 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1351 ReleaseReadLock(&afs_xsrvAddr);
1352 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1353 /* Found a server struct that is not multihomed and has the
1354 * IP address associated with it. A correct match.
1356 ReleaseSharedLock(&afs_xserver);
1360 if (nservers <= 0) panic("afs_GetServer: incorrect count of servers");
1361 ts = afs_FindServer(0, aport, uuidp, locktype);
1362 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1363 /* Found a server struct that is multihomed and same
1364 * uniqufier (same IP addrs). The above if statement is the
1365 * same as in InstallUVolumeEntry().
1367 ReleaseSharedLock(&afs_xserver);
1370 if (ts) oldts = ts; /* Will reuse if same uuid */
1373 UpgradeSToWLock(&afs_xserver,36);
1374 ObtainWriteLock(&afs_xsrvAddr,116);
1376 srvcount = afs_totalServers;
1378 /* Reuse/allocate a new server structure */
1382 newts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1383 if (!newts) panic("malloc of server struct");
1385 bzero((char *)newts, sizeof(struct server));
1387 /* Add the server struct to the afs_servers[] hash chain */
1388 srvhash = (uuidp ? (afs_uuid_hash(uuidp)%NSERVERS) : SHash(aserverp[0]));
1389 newts->next = afs_servers[srvhash];
1390 afs_servers[srvhash] = newts;
1393 /* Initialize the server structure */
1394 if (uuidp) { /* Multihomed */
1395 newts->sr_uuid = *uuidp;
1396 newts->sr_addr_uniquifier = addr_uniquifier;
1397 newts->flags |= SRVR_MULTIHOMED;
1399 if (acell) newts->cell = afs_GetCell(acell, 0);
1401 fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1403 /* For each IP address we are registering */
1404 for (k=0; k<nservers; k++) {
1405 iphash = SHash(aserverp[k]);
1407 /* Check if the srvAddr structure already exists. If so, remove
1408 * it from its server structure and add it to the new one.
1410 for (oldsa=afs_srvAddrs[iphash]; oldsa; oldsa=oldsa->next_bkt) {
1411 if ( (oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport) ) break;
1413 if (oldsa && (oldsa->server != newts)) {
1414 afs_RemoveSrvAddr(oldsa); /* Remove from its server struct */
1415 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1416 newts->addr = oldsa;
1419 /* Reuse/allocate a new srvAddr structure */
1423 newsa = (struct srvAddr *) afs_osi_Alloc(sizeof(struct srvAddr));
1424 if (!newsa) panic("malloc of srvAddr struct");
1425 afs_totalSrvAddrs++;
1426 bzero((char *)newsa, sizeof(struct srvAddr));
1428 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1429 newsa->next_bkt = afs_srvAddrs[iphash];
1430 afs_srvAddrs[iphash] = newsa;
1432 /* Hang off of the server structure */
1433 newsa->next_sa = newts->addr;
1434 newts->addr = newsa;
1436 /* Initialize the srvAddr Structure */
1437 newsa->sa_ip = aserverp[k];
1438 newsa->sa_portal = aport;
1441 /* Update the srvAddr Structure */
1442 newsa->server = newts;
1443 if (newts->flags & SRVR_ISDOWN)
1444 newsa->sa_flags |= SRVADDR_ISDOWN;
1445 if (uuidp) newsa->sa_flags |= SRVADDR_MH;
1446 else newsa->sa_flags &= ~SRVADDR_MH;
1448 /* Compute preference values and resort */
1449 if (!newsa->sa_iprank) {
1450 if (aport == fsport) {
1451 afs_SetServerPrefs(newsa); /* new fileserver rank */
1453 newsa->sa_iprank = 10000 + afs_randomMod127(); /* new vlserver rank */
1457 afs_SortOneServer(newts); /* Sort by rank */
1459 /* If we reused the server struct, remove any of its srvAddr
1460 * structs that will no longer be associated with this server.
1462 if (oldts) { /* reused the server struct */
1463 for (orphsa=newts->addr; orphsa; orphsa=nextsa) {
1464 nextsa = orphsa->next_sa;
1465 for (k=0; k<nservers; k++) {
1466 if (orphsa->sa_ip == aserverp[k]) break; /* belongs */
1468 if (k < nservers) continue; /* belongs */
1470 /* Have a srvAddr struct. Now get a server struct (if not already) */
1472 orphts = (struct server *) afs_osi_Alloc(sizeof(struct server));
1473 if (!orphts) panic("malloc of lo server struct");
1474 bzero((char *)orphts, sizeof(struct server));
1477 /* Add the orphaned server to the afs_servers[] hash chain.
1478 * Its iphash does not matter since we never look up the server
1479 * in the afs_servers table by its ip address (only by uuid -
1480 * which this has none).
1482 iphash = SHash(aserverp[k]);
1483 orphts->next = afs_servers[iphash];
1484 afs_servers[iphash] = orphts;
1486 if (acell) orphts->cell = afs_GetCell(acell, 0);
1489 /* Hang the srvAddr struct off of the server structure. The server
1490 * may have multiple srvAddrs, but it won't be marked multihomed.
1492 afs_RemoveSrvAddr(orphsa); /* remove */
1493 orphsa->next_sa = orphts->addr; /* hang off server struct */
1494 orphts->addr = orphsa;
1495 orphsa->server = orphts;
1496 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1497 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1501 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1503 struct afs_stats_SrvUpDownInfo *upDownP;
1504 /* With the introduction of this new record, we need to adjust the
1505 * proper individual & global server up/down info.
1507 if (aport == fsport) { /* File Server record */
1508 upDownP = (acell == 1) ?
1509 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1510 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1511 } else { /* VL Server record */
1512 upDownP = (acell == 1) ?
1513 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1514 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1516 (upDownP->numTtlRecords) += srvcount;
1517 afs_stats_cmperf.srvRecords += srvcount;
1518 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1519 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1522 ReleaseWriteLock(&afs_xsrvAddr);
1523 ReleaseWriteLock(&afs_xserver);
1525 } /* afs_GetServer */
1527 void afs_ActivateServer(sap)
1528 struct srvAddr *sap;
1530 osi_timeval_t currTime; /*Filled with current time*/
1531 osi_timeval_t *currTimeP; /*Ptr to above*/
1532 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record*/
1533 struct server *aserver = sap->server;
1535 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1537 * This server record has not yet been activated. Go for it,
1538 * recording its ``birth''.
1540 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1541 currTimeP = &currTime;
1542 osi_GetuTime(currTimeP);
1543 aserver->activationTime = currTime.tv_sec;
1544 if (sap->sa_portal == AFS_FSPORT) {
1545 upDownP = (aserver->cell->cell == 1) ?
1546 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1547 &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1548 } /*File Server record*/
1550 upDownP = (aserver->cell->cell == 1) ?
1551 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
1552 &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
1553 } /*VL Server record*/
1554 if (aserver->flags & SRVR_ISDOWN)
1555 (upDownP->numDownRecords)++;
1557 (upDownP->numUpRecords)++;
1558 (upDownP->numRecordsNeverDown)++;