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, struct rx_connection *rxconn)
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("afs: Lost contact with volume location server ",
243 sa, "", 1, code, rxconn);
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);
305 * If probe worked, or probe call not yet defined (for compatibility
306 * with old vlsevers), then we treat this server as running again
308 if (code == 0 || (code <= -450 && code >= -470)) {
309 if (tc->parent->srvr == sa) {
310 afs_MarkServerUpOrDown(sa, 0);
311 print_internet_address("afs: volume location server ", sa,
312 " is back up", 2, code, rxconn);
315 afs_PutConn(tc, rxconn, SHARED_LOCK);
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, struct rx_connection **rxconns,
522 int nconns, afs_int32 *results)
528 for(i = 0; i < nconns; i++){
530 sa = tc->parent->srvr;
532 if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
533 (tc->parent->srvr == sa)) {
535 print_internet_address("afs: file server ", sa, " is back up", 2,
536 results[i], rxconns[i]);
538 ObtainWriteLock(&afs_xserver, 244);
539 ObtainWriteLock(&afs_xsrvAddr, 245);
540 afs_MarkServerUpOrDown(sa, 0);
541 ReleaseWriteLock(&afs_xsrvAddr);
542 ReleaseWriteLock(&afs_xserver);
544 if (afs_waitForeverCount) {
545 afs_osi_Wakeup(&afs_waitForever);
548 if (results[i] < 0) {
550 afs_ServerDown(sa, results[i], rxconns[i]);
551 ForceNewConnections(sa); /* multi homed clients */
558 CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
559 struct afs_conn **conns)
566 caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
567 osi_Assert(caps != NULL);
568 memset(caps, 0, nconns * sizeof(Capabilities));
570 results = afs_osi_Alloc(nconns * sizeof (afs_int32));
571 osi_Assert(results != NULL);
574 multi_Rx(rxconns,nconns)
576 multi_RXAFS_GetCapabilities(&caps[multi_i]);
577 results[multi_i] = multi_error;
581 for ( i = 0 ; i < nconns ; i++ ) {
582 ts = conns[i]->parent->srvr->server;
585 ts->capabilities = 0;
586 ts->flags |= SCAPS_KNOWN;
587 if ( results[i] == RXGEN_OPCODE ) {
588 /* Mark server as up - it responded */
592 if ( results[i] >= 0 )
593 /* we currently handle 32-bits of capabilities */
594 if (caps[i].Capabilities_len > 0) {
595 ts->capabilities = caps[i].Capabilities_val[0];
596 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
597 caps[i].Capabilities_val = NULL;
598 caps[i].Capabilities_len = 0;
601 CkSrv_MarkUpDown(conns, rxconns, nconns, results);
603 afs_osi_Free(caps, nconns * sizeof(Capabilities));
604 afs_osi_Free(results, nconns * sizeof(afs_int32));
607 /* check down servers (if adown), or running servers (if !adown) */
609 afs_CheckServers(int adown, struct cell *acellp)
611 afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
614 /* adown: AFS_LS_UP - check only up
615 * AFS_LS_DOWN - check only down.
616 * AFS_LS_ALL - check all */
618 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
619 void (*func1) (int nservers, struct rx_connection **rxconns,
620 struct afs_conn **conns),
621 void (*func2) (int nservers, struct rx_connection **rxconns,
622 struct afs_conn **conns))
624 struct vrequest treq;
627 struct afs_conn *tc = NULL;
632 struct srvAddr **addrs;
633 struct afs_conn **conns;
635 struct rx_connection **rxconns;
636 afs_int32 *conntimer;
638 AFS_STATCNT(afs_CheckServers);
641 * No sense in doing the server checks if we are running in disconnected
644 if (AFS_IS_DISCONNECTED)
647 if ((code = afs_InitReq(&treq, afs_osi_credp)))
649 ObtainReadLock(&afs_xserver); /* Necessary? */
650 ObtainReadLock(&afs_xsrvAddr);
653 for (i = 0; i < NSERVERS; i++) {
654 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
659 addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
660 osi_Assert(addrs != NULL);
662 for (i = 0; i < NSERVERS; i++) {
663 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
664 if (j >= srvAddrCount)
670 ReleaseReadLock(&afs_xsrvAddr);
671 ReleaseReadLock(&afs_xserver);
673 conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
674 osi_Assert(conns != NULL);
675 rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
676 osi_Assert(rxconns != NULL);
677 conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
678 osi_Assert(conntimer != NULL);
681 for (i = 0; i < j; i++) {
682 struct rx_connection *rxconn;
688 /* See if a cell to check was specified. If it is spec'd and not
689 * this server's cell, just skip the server.
691 if (acellp && acellp != ts->cell)
694 if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
695 || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
698 /* check vlserver with special code */
699 if (sa->sa_portal == AFS_VLPORT) {
701 CheckVLServer(sa, &treq);
705 if (!ts->cell) /* not really an active server, anyway, it must */
706 continue; /* have just been added by setsprefs */
708 /* get a connection, even if host is down; bumps conn ref count */
709 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
710 tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
711 1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
713 afs_PutUser(tu, SHARED_LOCK);
717 if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
719 rxconns[nconns]=rxconn;
720 if (sa->sa_flags & SRVADDR_ISDOWN) {
721 rx_SetConnDeadTime(rxconn, 3);
727 } else /* not holding, kill ref */
728 afs_PutConn(tc, rxconn, SHARED_LOCK);
729 } /* Outer loop over addrs */
731 afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
734 (*func1)(nconns, rxconns, conns);
737 (*func2)(nconns, rxconns, conns);
740 for (i = 0; i < nconns; i++) {
741 if (conntimer[i] == 1)
742 rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
743 afs_PutConn(conns[i], rxconns[i], SHARED_LOCK); /* done with it now */
746 afs_osi_Free(conns, j * sizeof(struct afs_conn *));
747 afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
748 afs_osi_Free(conntimer, j * sizeof(afs_int32));
750 } /*afs_CheckServers*/
753 /* find a server structure given the host address */
755 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
762 AFS_STATCNT(afs_FindServer);
764 i = afs_uuid_hash(uuidp) % NSERVERS;
765 for (ts = afs_servers[i]; ts; ts = ts->next) {
766 if ((ts->flags & SRVR_MULTIHOMED)
768 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
769 == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
774 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
775 if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
782 } /*afs_FindServer */
785 /* some code for creating new server structs and setting preferences follows
786 * in the next few lines...
789 #define MAXDEFRANK 60000
790 #define DEFRANK 40000
792 /* Random number generator and constants from KnuthV2 2d ed, p170 */
798 a is 0.73m should be 0.01m .. 0.99m
799 c is more or less immaterial. 1 or a is suggested.
801 NB: LOW ORDER BITS are not very random. To get small random numbers,
802 treat result as <1, with implied binary point, and multiply by
804 NB: Has to be unsigned, since shifts on signed quantities may preserve
807 /* added rxi_getaddr() to try to get as much initial randomness as
808 possible, since at least one customer reboots ALL their clients
809 simultaneously -- so osi_Time is bound to be the same on some of the
810 clients. This is probably OK, but I don't want to see too much of it.
813 #define ranstage(x) (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
818 static afs_int32 state = 0;
821 AFS_STATCNT(afs_random);
826 * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
827 * bits are in a tv_usec
829 state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
830 state += (t.tv_sec & 0xff);
831 for (i = 0; i < 30; i++) {
841 /* returns int 0..14 using the high bits of a pseudo-random number instead of
842 the low bits, as the low bits are "less random" than the high ones...
843 slight roundoff error exists, an excercise for the reader.
844 need to multiply by something with lots of ones in it, so multiply by
845 8 or 16 is right out.
848 afs_randomMod15(void)
852 temp = afs_random() >> 4;
853 temp = (temp * 15) >> 28;
859 afs_randomMod127(void)
863 temp = afs_random() >> 7;
864 temp = (temp * 127) >> 25;
869 /* afs_SortOneServer()
870 * Sort all of the srvAddrs, of a server struct, by rank from low to high.
873 afs_SortOneServer(struct server *asp)
875 struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
878 for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
880 lowsa = *rootsa; /* lowest sa is the first one */
881 lowrank = lowsa->sa_iprank;
883 for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
884 rank = tsa->next_sa->sa_iprank;
885 if (rank < lowrank) {
887 lowsa = tsa->next_sa;
888 lowrank = lowsa->sa_iprank;
891 if (lowprev) { /* found one lower, so rearrange them */
892 lowprev->next_sa = lowsa->next_sa;
893 lowsa->next_sa = *rootsa;
900 * Sort the pointer to servers by the server's rank (its lowest rank).
901 * It is assumed that the server already has its IP addrs sorted (the
902 * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
905 afs_SortServers(struct server *aservers[], int count)
910 AFS_STATCNT(afs_SortServers);
912 for (i = 0; i < count; i++) {
915 for (low = i, j = i + 1; j <= count; j++) {
916 if ((!aservers[j]) || (!aservers[j]->addr))
918 if ((!aservers[low]) || (!aservers[low]->addr))
920 if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
926 aservers[i] = aservers[low];
930 } /*afs_SortServers */
932 /* afs_SetServerPrefs is rather system-dependent. It pokes around in kernel
933 data structures to determine what the local IP addresses and subnet masks
934 are in order to choose which server(s) are on the local subnet.
936 As I see it, there are several cases:
937 1. The server address is one of this host's local addresses. In this case
938 this server is to be preferred over all others.
939 2. The server is on the same subnet as one of the this host's local
940 addresses. (ie, an odd-sized subnet, not class A,B,orC)
941 3. The server is on the same net as this host (class A,B or C)
942 4. The server is on a different logical subnet or net than this host, but
943 this host is a 'metric 0 gateway' to it. Ie, two address-spaces share
945 5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
947 6. This host and the server are disjoint.
949 That is a rough order of preference. If a point-to-point link has a high
950 metric, I'm assuming that it is a very slow link, and putting it at the
951 bottom of the list (at least until RX works better over slow links). If
952 its metric is 1, I'm assuming that it's relatively fast (T1) and putting
954 It's not easy to check for case #4, so I'm ignoring it for the time being.
956 BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
957 That could be used to prefer certain servers fairly easily. Maybe some
960 NOTE: this code is very system-dependent, and very dependent on the TCP/IP
961 protocols (well, addresses that are stored in uint32s, at any rate).
964 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
965 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
967 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
968 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
973 #define PPWEIGHT 4096
977 #ifdef AFS_USERSPACE_IP_ADDR
979 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
982 * The IP addresses and ranks are determined by afsd (in user space) and
983 * passed into the kernel at startup time through the AFSOP_ADVISEADDR
984 * system call. These are stored in the data structure
985 * called 'afs_cb_interface'.
987 * struct srvAddr *sa; remote server
988 * afs_int32 addr; one of my local addr in net order
989 * afs_uint32 subnetmask; subnet mask of local addr in net order
993 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
994 afs_uint32 subnetmask)
996 afs_uint32 myAddr, myNet, mySubnet, netMask;
997 afs_uint32 serverAddr;
999 myAddr = ntohl(addr); /* one of my IP addr in host order */
1000 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1001 subnetmask = ntohl(subnetmask); /* subnet mask in host order */
1003 if (IN_CLASSA(myAddr))
1004 netMask = IN_CLASSA_NET;
1005 else if (IN_CLASSB(myAddr))
1006 netMask = IN_CLASSB_NET;
1007 else if (IN_CLASSC(myAddr))
1008 netMask = IN_CLASSC_NET;
1012 myNet = myAddr & netMask;
1013 mySubnet = myAddr & subnetmask;
1015 if ((serverAddr & netMask) == myNet) {
1016 if ((serverAddr & subnetmask) == mySubnet) {
1017 if (serverAddr == myAddr) { /* same machine */
1018 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1019 } else { /* same subnet */
1020 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1022 } else { /* same net */
1023 sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1028 #else /* AFS_USERSPACE_IP_ADDR */
1029 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && (! defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1031 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1033 struct sockaddr_in *sin;
1036 if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1037 if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1039 if (SA2ULONG(sin) == ntohl(sa->sa_ip)) { /* ie, ME!!! */
1040 sa->sa_iprank = TOPR;
1042 t = HI + ifa->ia_ifp->if_metric; /* case #2 */
1043 if (sa->sa_iprank > t)
1047 t = MED + ifa->ia_ifp->if_metric; /* case #3 */
1048 if (sa->sa_iprank > t)
1052 #if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
1053 /* check for case #4 -- point-to-point link */
1054 if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1055 && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1056 if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1059 t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1060 if (sa->sa_iprank > t)
1063 #endif /* IFF_POINTOPOINT */
1065 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1066 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV) || defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1068 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1071 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1073 struct sockaddr sout;
1074 struct sockaddr_in *sin;
1075 #if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
1081 afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1082 afs_uint32 serverAddr;
1084 if (rx_ifaddr_address_family(ifa) != AF_INET)
1086 t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1088 sin = (struct sockaddr_in *)&sout;
1089 myAddr = ntohl(sin->sin_addr.s_addr); /* one of my IP addr in host order */
1093 serverAddr = ntohl(sa->sa_ip); /* server's IP addr in host order */
1094 t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1096 sin = (struct sockaddr_in *)&sout;
1097 subnetmask = ntohl(sin->sin_addr.s_addr); /* subnet mask in host order */
1101 t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1103 sin = (struct sockaddr_in *)&sout;
1104 myDstaddr = ntohl(sin->sin_addr.s_addr);
1109 if (IN_CLASSA(myAddr))
1110 netMask = IN_CLASSA_NET;
1111 else if (IN_CLASSB(myAddr))
1112 netMask = IN_CLASSB_NET;
1113 else if (IN_CLASSC(myAddr))
1114 netMask = IN_CLASSC_NET;
1118 myNet = myAddr & netMask;
1119 mySubnet = myAddr & subnetmask;
1121 if ((serverAddr & netMask) == myNet) {
1122 if ((serverAddr & subnetmask) == mySubnet) {
1123 if (serverAddr == myAddr) { /* same machine */
1124 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1125 } else { /* same subnet */
1126 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1128 } else { /* same net */
1129 sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1132 #ifdef IFF_POINTTOPOINT
1133 /* check for case #4 -- point-to-point link */
1134 if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1135 && (myDstaddr == serverAddr)) {
1136 if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1139 t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1140 if (sa->sa_iprank > t)
1143 #endif /* IFF_POINTTOPOINT */
1145 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1146 #endif /* else AFS_USERSPACE_IP_ADDR */
1148 #ifdef AFS_SGI62_ENV
1150 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1153 afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1154 return 0; /* Never match, so we enumerate everyone */
1156 #endif /* AFS_SGI62_ENV */
1158 afs_SetServerPrefs(struct srvAddr *const sa)
1160 #if defined(AFS_USERSPACE_IP_ADDR)
1164 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1165 afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1166 afs_cb_interface.subnetmask[i]);
1168 #else /* AFS_USERSPACE_IP_ADDR */
1169 #if defined(AFS_SUN5_ENV)
1170 #ifdef AFS_SUN510_ENV
1173 extern struct ill_s *ill_g_headp;
1174 long *addr = (long *)ill_g_headp;
1178 int subnet, subnetmask, net, netmask;
1181 #ifdef AFS_SUN510_ENV
1182 rw_enter(&afsifinfo_lock, RW_READER);
1184 for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1186 if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1187 netmask = IN_CLASSA_NET;
1188 } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1189 netmask = IN_CLASSB_NET;
1190 } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1191 netmask = IN_CLASSC_NET;
1195 net = afsifinfo[i].ipaddr & netmask;
1198 /* XXXXXX Do the individual ip ranking below XXXXX */
1199 if ((sa->sa_ip & netmask) == net) {
1200 if ((sa->sa_ip & subnetmask) == subnet) {
1201 if (afsifinfo[i].ipaddr == sa->sa_ip) { /* ie, ME! */
1202 sa->sa_iprank = TOPR;
1204 sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1207 sa->sa_iprank = MED + afsifinfo[i].metric; /* case #3 */
1210 sa->sa_iprank = LO + afsifinfo[i].metric; /* case #4 */
1212 /* check for case #5 -- point-to-point link */
1213 if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1214 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1216 if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1217 sa->sa_iprank = MAXDEFRANK;
1219 sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1224 rw_exit(&afsifinfo_lock);
1226 for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1227 ill = ill->ill_next) {
1228 /* Make sure this is an IPv4 ILL */
1231 for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1232 subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1233 subnetmask = ipif->ipif_net_mask;
1235 * Generate the local net using the local address and
1236 * whate we know about Class A, B and C networks.
1238 if (IN_CLASSA(ipif->ipif_local_addr)) {
1239 netmask = IN_CLASSA_NET;
1240 } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1241 netmask = IN_CLASSB_NET;
1242 } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1243 netmask = IN_CLASSC_NET;
1247 net = ipif->ipif_local_addr & netmask;
1249 /* XXXXXX Do the individual ip ranking below XXXXX */
1250 if ((sa->sa_ip & netmask) == net) {
1251 if ((sa->sa_ip & subnetmask) == subnet) {
1252 if (ipif->ipif_local_addr == sa->sa_ip) { /* ie, ME! */
1253 sa->sa_iprank = TOPR;
1255 sa->sa_iprank = HI + ipif->ipif_metric; /* case #2 */
1258 sa->sa_iprank = MED + ipif->ipif_metric; /* case #3 */
1261 sa->sa_iprank = LO + ipif->ipif_metric; /* case #4 */
1263 /* check for case #5 -- point-to-point link */
1264 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1265 && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1267 if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1268 sa->sa_iprank = MAXDEFRANK;
1270 sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1275 #endif /* AFS_SUN510_ENV */
1278 rx_ifnet_t ifn = NULL;
1279 struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1280 struct sockaddr_in *sin;
1283 ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1284 if (ifn) { /* local, more or less */
1286 if (ifn->if_flags & IFF_LOOPBACK) {
1287 sa->sa_iprank = TOPR;
1290 #endif /* IFF_LOOPBACK */
1291 sin = (struct sockaddr_in *)IA_SIN(ifad);
1292 if (SA2ULONG(sin) == sa->sa_ip) {
1293 sa->sa_iprank = TOPR;
1296 #ifdef IFF_BROADCAST
1297 if (ifn->if_flags & IFF_BROADCAST) {
1298 if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1303 #endif /* IFF_BROADCAST */
1304 #ifdef IFF_POINTOPOINT
1305 if (ifn->if_flags & IFF_POINTOPOINT) {
1306 if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1307 if (ifn->if_metric > 4) {
1311 sa->sa_iprank = ifn->if_metric;
1314 #endif /* IFF_POINTOPOINT */
1315 sa->sa_iprank += MED + ifn->if_metric; /* couldn't find anything better */
1317 #else /* USEIFADDR */
1320 #ifdef AFS_SGI62_ENV
1321 (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1322 (caddr_t) sa, NULL);
1323 #elif defined(AFS_DARWIN80_ENV)
1331 if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1332 for (m = 0; m < count; m++) {
1333 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1334 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1335 afsi_SetServerIPRank(sa, ifads[j]);
1338 ifnet_free_address_list(ifads);
1341 ifnet_list_free(ifns);
1344 #elif defined(AFS_DARWIN_ENV)
1348 TAILQ_FOREACH(ifn, &ifnet, if_link) {
1349 TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1350 afsi_SetServerIPRank(sa, ifa);
1352 #elif defined(AFS_FBSD_ENV)
1354 struct in_ifaddr *ifa;
1355 #if defined(AFS_FBSD80_ENV)
1356 TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
1358 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1360 afsi_SetServerIPRank(sa, &ifa->ia_ifa);
1362 #elif defined(AFS_OBSD_ENV)
1364 extern struct in_ifaddrhead in_ifaddr;
1365 struct in_ifaddr *ifa;
1366 for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1367 afsi_SetServerIPRank(sa, ifa);
1369 #elif defined(AFS_NBSD40_ENV)
1371 extern struct in_ifaddrhead in_ifaddrhead;
1372 struct in_ifaddr *ifa;
1373 for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1374 afsi_SetServerIPRank(sa, ifa);
1378 struct in_ifaddr *ifa;
1379 for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1380 afsi_SetServerIPRank(sa, ifa);
1383 #endif /* USEIFADDR */
1387 #endif /* AFS_SUN5_ENV */
1388 #endif /* else AFS_USERSPACE_IP_ADDR */
1389 sa->sa_iprank += afs_randomMod15();
1392 } /* afs_SetServerPrefs */
1400 /* afs_FlushServer()
1401 * The addresses on this server struct has changed in some way and will
1402 * clean up all other structures that may reference it.
1403 * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
1406 afs_FlushServer(struct server *srvp, struct volume *tv)
1409 struct server *ts, **pts;
1411 /* Find any volumes residing on this server and flush their state */
1412 afs_ResetVolumes(srvp, tv);
1414 /* Flush all callbacks in the all vcaches for this specific server */
1415 afs_FlushServerCBs(srvp);
1417 /* Remove all the callbacks structs */
1419 struct afs_cbr *cb, *cbnext;
1421 for (cb = srvp->cbrs; cb; cb = cbnext) {
1424 } srvp->cbrs = (struct afs_cbr *)0;
1427 /* If no more srvAddr structs hanging off of this server struct,
1431 /* Remove the server structure from the cell list - if there */
1432 afs_RemoveCellEntry(srvp);
1434 /* Remove from the afs_servers hash chain */
1435 for (i = 0; i < NSERVERS; i++) {
1436 for (pts = &(afs_servers[i]), ts = *pts; ts;
1437 pts = &(ts->next), ts = *pts) {
1445 *pts = ts->next; /* Found it. Remove it */
1446 afs_osi_Free(ts, sizeof(struct server)); /* Free it */
1452 /* afs_RemoveSrvAddr()
1453 * This removes a SrvAddr structure from its server structure.
1454 * The srvAddr struct is not free'd because it connections may still
1455 * be open to it. It is up to the calling process to make sure it
1456 * remains connected to a server struct.
1457 * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1458 * It is not removed from the afs_srvAddrs hash chain.
1459 * If resetting volumes, do not reset volume tv
1462 afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
1464 struct srvAddr **psa, *sa;
1471 /* Find the srvAddr in the server's list and remove it */
1472 for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1480 /* Flush the server struct since it's IP address has changed */
1481 afs_FlushServer(srv, tv);
1485 /* afs_GetCapabilities
1486 * Try and retrieve capabilities of a given file server. Carps on actual
1487 * failure. Servers are not expected to support this RPC. */
1489 afs_GetCapabilities(struct server *ts)
1491 Capabilities caps = {0, NULL};
1492 struct vrequest treq;
1493 struct afs_conn *tc;
1494 struct unixuser *tu;
1495 struct rx_connection *rxconn;
1498 if ( !ts || !ts->cell )
1500 if ( !afs_osi_credp )
1503 if ((code = afs_InitReq(&treq, afs_osi_credp)))
1505 tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1508 tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1509 SHARED_LOCK, 0, &rxconn);
1510 afs_PutUser(tu, SHARED_LOCK);
1513 /* InitCallBackStateN, triggered by our RPC, may need this */
1514 ReleaseWriteLock(&afs_xserver);
1515 code = RXAFS_GetCapabilities(rxconn, &caps);
1516 ObtainWriteLock(&afs_xserver, 723);
1517 /* we forced a conn above; important we mark it down if needed */
1518 if ((code < 0) && (code != RXGEN_OPCODE)) {
1519 afs_ServerDown(tc->parent->srvr, code, rxconn);
1520 ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1522 afs_PutConn(tc, rxconn, SHARED_LOCK);
1523 if ( code && code != RXGEN_OPCODE ) {
1524 afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1525 /* better not be anything to free. we failed! */
1529 ts->flags |= SCAPS_KNOWN;
1531 if ( caps.Capabilities_len > 0 ) {
1532 ts->capabilities = caps.Capabilities_val[0];
1533 xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1534 caps.Capabilities_len = 0;
1535 caps.Capabilities_val = NULL;
1540 static struct server *
1541 afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
1542 struct server **oldts, afs_int32 addr_uniquifier)
1544 struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
1545 if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1546 /* Found a server struct that is multihomed and same
1547 * uniqufier (same IP addrs). The above if statement is the
1548 * same as in InstallUVolumeEntry().
1553 *oldts = ts; /* Will reuse if same uuid */
1558 * Return an updated and properly initialized server structure.
1560 * Takes a server ID, cell, and port.
1561 * If server does not exist, then one will be created.
1562 * @param[in] aserverp
1563 * The server address in network byte order
1564 * @param[in] nservers
1565 * The number of IP addresses claimed by the server
1567 * The cell the server is in
1569 * The port for the server (fileserver or vlserver) in network byte order
1570 * @param[in] locktype
1571 * The type of lock to hold when iterating server hash (unused).
1573 * The uuid for servers supporting one.
1574 * @param[in] addr_uniquifier
1575 * The vldb-provider per-instantiated-server uniquifer counter.
1577 * A volume not to reset information for if the server addresses
1581 * A server structure matching the request.
1584 afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
1585 u_short aport, afs_int32 locktype, afsUUID * uuidp,
1586 afs_int32 addr_uniquifier, struct volume *tv)
1588 struct server *oldts = 0, *ts, *newts, *orphts = 0;
1589 struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1590 afs_int32 iphash, k, srvcount = 0;
1591 unsigned int srvhash;
1593 AFS_STATCNT(afs_GetServer);
1595 ObtainSharedLock(&afs_xserver, 13);
1597 /* Check if the server struct exists and is up to date */
1600 panic("afs_GetServer: incorrect count of servers");
1601 ObtainReadLock(&afs_xsrvAddr);
1602 ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1603 ReleaseReadLock(&afs_xsrvAddr);
1604 if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1605 /* Found a server struct that is not multihomed and has the
1606 * IP address associated with it. A correct match.
1608 ReleaseSharedLock(&afs_xserver);
1613 panic("afs_GetServer: incorrect count of servers");
1615 ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
1617 ReleaseSharedLock(&afs_xserver);
1623 * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
1624 * Do a little dance and see if we can grab xvcb. If not, we
1625 * need to recheck that oldts is still right after a drop and reobtain.
1627 if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
1628 ReleaseSharedLock(&afs_xserver);
1629 ObtainWriteLock(&afs_xvcb, 299);
1630 ObtainWriteLock(&afs_xserver, 35);
1632 /* we don't know what changed while we didn't hold the lock */
1634 ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
1637 ReleaseWriteLock(&afs_xserver);
1638 ReleaseWriteLock(&afs_xvcb);
1642 UpgradeSToWLock(&afs_xserver, 36);
1644 ObtainWriteLock(&afs_xsrvAddr, 116);
1645 srvcount = afs_totalServers;
1647 /* Reuse/allocate a new server structure */
1651 newts = afs_osi_Alloc(sizeof(struct server));
1653 panic("malloc of server struct");
1655 memset(newts, 0, sizeof(struct server));
1657 /* Add the server struct to the afs_servers[] hash chain */
1659 (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1660 newts->next = afs_servers[srvhash];
1661 afs_servers[srvhash] = newts;
1664 /* Initialize the server structure */
1665 if (uuidp) { /* Multihomed */
1666 newts->sr_uuid = *uuidp;
1667 newts->sr_addr_uniquifier = addr_uniquifier;
1668 newts->flags |= SRVR_MULTIHOMED;
1671 newts->cell = afs_GetCell(acell, 0);
1673 /* For each IP address we are registering */
1674 for (k = 0; k < nservers; k++) {
1675 iphash = SHash(aserverp[k]);
1677 /* Check if the srvAddr structure already exists. If so, remove
1678 * it from its server structure and add it to the new one.
1680 for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1681 if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1684 if (oldsa && (oldsa->server != newts)) {
1685 afs_RemoveSrvAddr(oldsa, tv); /* Remove from its server struct */
1686 oldsa->next_sa = newts->addr; /* Add to the new server struct */
1687 newts->addr = oldsa;
1690 /* Reuse/allocate a new srvAddr structure */
1694 newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1696 panic("malloc of srvAddr struct");
1697 afs_totalSrvAddrs++;
1698 memset(newsa, 0, sizeof(struct srvAddr));
1700 /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1701 newsa->next_bkt = afs_srvAddrs[iphash];
1702 afs_srvAddrs[iphash] = newsa;
1704 /* Hang off of the server structure */
1705 newsa->next_sa = newts->addr;
1706 newts->addr = newsa;
1708 /* Initialize the srvAddr Structure */
1709 newsa->sa_ip = aserverp[k];
1710 newsa->sa_portal = aport;
1713 /* Update the srvAddr Structure */
1714 newsa->server = newts;
1715 if (newts->flags & SRVR_ISDOWN)
1716 newsa->sa_flags |= SRVADDR_ISDOWN;
1718 newsa->sa_flags |= SRVADDR_MH;
1720 newsa->sa_flags &= ~SRVADDR_MH;
1722 /* Compute preference values and resort */
1723 if (!newsa->sa_iprank) {
1724 afs_SetServerPrefs(newsa); /* new server rank */
1727 afs_SortOneServer(newts); /* Sort by rank */
1729 /* If we reused the server struct, remove any of its srvAddr
1730 * structs that will no longer be associated with this server.
1732 if (oldts) { /* reused the server struct */
1733 for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1734 nextsa = orphsa->next_sa;
1735 for (k = 0; k < nservers; k++) {
1736 if (orphsa->sa_ip == aserverp[k])
1737 break; /* belongs */
1740 continue; /* belongs */
1742 /* Have a srvAddr struct. Now get a server struct (if not already) */
1744 orphts = afs_osi_Alloc(sizeof(struct server));
1746 panic("malloc of lo server struct");
1747 memset(orphts, 0, sizeof(struct server));
1750 /* Add the orphaned server to the afs_servers[] hash chain.
1751 * Its iphash does not matter since we never look up the server
1752 * in the afs_servers table by its ip address (only by uuid -
1753 * which this has none).
1755 iphash = SHash(aserverp[k]);
1756 orphts->next = afs_servers[iphash];
1757 afs_servers[iphash] = orphts;
1760 orphts->cell = afs_GetCell(acell, 0);
1763 /* Hang the srvAddr struct off of the server structure. The server
1764 * may have multiple srvAddrs, but it won't be marked multihomed.
1766 afs_RemoveSrvAddr(orphsa, tv); /* remove */
1767 orphsa->next_sa = orphts->addr; /* hang off server struct */
1768 orphts->addr = orphsa;
1769 orphsa->server = orphts;
1770 orphsa->sa_flags |= SRVADDR_NOUSE; /* flag indicating not in use */
1771 orphsa->sa_flags &= ~SRVADDR_MH; /* Not multihomed */
1774 /* We can't need this below, and won't reacquire */
1775 ReleaseWriteLock(&afs_xvcb);
1777 srvcount = afs_totalServers - srvcount; /* # servers added and removed */
1779 struct afs_stats_SrvUpDownInfo *upDownP;
1780 /* With the introduction of this new record, we need to adjust the
1781 * proper individual & global server up/down info.
1783 upDownP = GetUpDownStats(newts);
1784 upDownP->numTtlRecords += srvcount;
1785 afs_stats_cmperf.srvRecords += srvcount;
1786 if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1787 afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1789 /* We can't need this below, and won't reacquire */
1790 ReleaseWriteLock(&afs_xvcb);
1792 ReleaseWriteLock(&afs_xsrvAddr);
1794 if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1795 afs_GetCapabilities(newts);
1797 ReleaseWriteLock(&afs_xserver);
1799 } /* afs_GetServer */
1802 afs_ActivateServer(struct srvAddr *sap)
1804 osi_timeval_t currTime; /*Filled with current time */
1805 osi_timeval_t *currTimeP; /*Ptr to above */
1806 struct afs_stats_SrvUpDownInfo *upDownP; /*Ptr to up/down info record */
1807 struct server *aserver = sap->server;
1809 if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1811 * This server record has not yet been activated. Go for it,
1812 * recording its ``birth''.
1814 aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1815 currTimeP = &currTime;
1816 osi_GetuTime(currTimeP);
1817 aserver->activationTime = currTime.tv_sec;
1818 upDownP = GetUpDownStats(aserver);
1819 if (aserver->flags & SRVR_ISDOWN) {
1820 upDownP->numDownRecords++;
1822 upDownP->numUpRecords++;
1823 upDownP->numRecordsNeverDown++;
1829 afs_RemoveAllConns(void)
1832 struct server *ts, *nts;
1835 ObtainReadLock(&afs_xserver);
1836 ObtainWriteLock(&afs_xconn, 1001);
1838 /*printf("Destroying connections ... ");*/
1839 for (i = 0; i < NSERVERS; i++) {
1840 for (ts = afs_servers[i]; ts; ts = nts) {
1842 for (sa = ts->addr; sa; sa = sa->next_sa) {
1844 afs_ReleaseConns(sa->conns);
1851 /*printf("done\n");*/
1853 ReleaseWriteLock(&afs_xconn);
1854 ReleaseReadLock(&afs_xserver);
1859 afs_MarkAllServersUp(void)
1865 ObtainWriteLock(&afs_xserver, 721);
1866 ObtainWriteLock(&afs_xsrvAddr, 722);
1867 for (i = 0; i< NSERVERS; i++) {
1868 for (ts = afs_servers[i]; ts; ts = ts->next) {
1869 for (sa = ts->addr; sa; sa = sa->next_sa) {
1870 afs_MarkServerUpOrDown(sa, 0);
1874 ReleaseWriteLock(&afs_xsrvAddr);
1875 ReleaseWriteLock(&afs_xserver);