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
10 #include <afs/param.h>
21 #include <WINNT\syscfg.h>
25 osi_rwlock_t cm_serverLock;
27 cm_server_t *cm_allServersp;
28 afs_uint32 cm_numFileServers = 0;
29 afs_uint32 cm_numVldbServers = 0;
32 cm_ForceNewConnectionsAllServers(void)
36 lock_ObtainWrite(&cm_serverLock);
37 for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
38 cm_GetServerNoLock(tsp);
39 cm_ForceNewConnections(tsp);
40 cm_PutServerNoLock(tsp);
42 lock_ReleaseWrite(&cm_serverLock);
46 cm_PingServer(cm_server_t *tsp)
51 struct rx_connection * rxconnp;
54 Capabilities caps = {0, 0};
58 lock_ObtainMutex(&tsp->mx);
59 if (tsp->flags & CM_SERVERFLAG_PINGING) {
61 osi_SleepM((LONG_PTR)tsp, &tsp->mx);
62 lock_ObtainMutex(&tsp->mx);
64 if (tsp->waitCount == 0)
65 tsp->flags &= ~CM_SERVERFLAG_PINGING;
67 osi_Wakeup((LONG_PTR)tsp);
68 lock_ReleaseMutex(&tsp->mx);
71 tsp->flags |= CM_SERVERFLAG_PINGING;
72 wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
73 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
74 lock_ReleaseMutex(&tsp->mx);
76 code = cm_ConnByServer(tsp, cm_rootUserp, &connp);
78 /* now call the appropriate ping call. Drop the timeout if
79 * the server is known to be down, so that we don't waste a
80 * lot of time retiming out down servers.
83 osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x",
84 osi_LogSaveString(afsd_logp, hoststr),
85 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
86 wasDown ? "down" : "up",
89 rxconnp = cm_GetRxConn(connp);
91 rx_SetConnDeadTime(rxconnp, 10);
92 if (tsp->type == CM_SERVER_VLDB) {
93 code = VL_ProbeServer(rxconnp);
97 code = RXAFS_GetCapabilities(rxconnp, &caps);
98 if (code == RXGEN_OPCODE)
99 code = RXAFS_GetTime(rxconnp, &secs, &usecs);
102 rx_SetConnDeadTime(rxconnp, ConnDeadtimeout);
103 rx_PutConnection(rxconnp);
105 } /* got an unauthenticated connection to this server */
107 lock_ObtainMutex(&tsp->mx);
109 /* mark server as up */
110 tsp->flags &= ~CM_SERVERFLAG_DOWN;
113 /* we currently handle 32-bits of capabilities */
114 if (caps.Capabilities_len > 0) {
115 tsp->capabilities = caps.Capabilities_val[0];
116 free(caps.Capabilities_val);
117 caps.Capabilities_len = 0;
118 caps.Capabilities_val = 0;
120 tsp->capabilities = 0;
123 osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x",
124 osi_LogSaveString(afsd_logp, hoststr),
125 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
128 /* Now update the volume status if necessary */
130 cm_server_vols_t * tsrvp;
134 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
135 for (i=0; i<NUM_SERVER_VOLS; i++) {
136 if (tsrvp->ids[i] != 0) {
139 lock_ReleaseMutex(&tsp->mx);
140 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
141 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
142 lock_ObtainMutex(&tsp->mx);
144 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
152 /* mark server as down */
153 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
154 tsp->flags |= CM_SERVERFLAG_DOWN;
155 tsp->downTime = time(NULL);
157 if (code != VRESTARTING)
158 cm_ForceNewConnections(tsp);
160 osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x",
161 osi_LogSaveString(afsd_logp, hoststr),
162 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
165 /* Now update the volume status if necessary */
167 cm_server_vols_t * tsrvp;
171 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
172 for (i=0; i<NUM_SERVER_VOLS; i++) {
173 if (tsrvp->ids[i] != 0) {
176 lock_ReleaseMutex(&tsp->mx);
177 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
178 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
179 lock_ObtainMutex(&tsp->mx);
181 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
190 if (tsp->waitCount == 0)
191 tsp->flags &= ~CM_SERVERFLAG_PINGING;
193 osi_Wakeup((LONG_PTR)tsp);
194 lock_ReleaseMutex(&tsp->mx);
197 #define MULTI_CHECKSERVERS 1
198 #ifndef MULTI_CHECKSERVERS
199 void cm_CheckServers(afs_uint32 flags, cm_cell_t *cellp)
201 /* ping all file servers, up or down, with unauthenticated connection,
202 * to find out whether we have all our callbacks from the server still.
203 * Also, ping down VLDBs.
210 lock_ObtainWrite(&cm_serverLock);
211 for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
212 cm_GetServerNoLock(tsp);
213 lock_ReleaseWrite(&cm_serverLock);
215 /* now process the server */
216 lock_ObtainMutex(&tsp->mx);
219 isDown = tsp->flags & CM_SERVERFLAG_DOWN;
220 isFS = tsp->type == CM_SERVER_FILE;
222 /* only do the ping if the cell matches the requested cell, or we're
223 * matching all cells (cellp == NULL), and if we've requested to ping
224 * this type of {up, down} servers.
226 if ((cellp == NULL || cellp == tsp->cellp) &&
227 ((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
228 (!isDown && (flags & CM_FLAG_CHECKUPSERVERS))) &&
229 ((!(flags & CM_FLAG_CHECKVLDBSERVERS) ||
230 !isFS && (flags & CM_FLAG_CHECKVLDBSERVERS)) &&
231 (!(flags & CM_FLAG_CHECKFILESERVERS) ||
232 isFS && (flags & CM_FLAG_CHECKFILESERVERS)))) {
234 } /* we're supposed to check this up/down server */
235 lock_ReleaseMutex(&tsp->mx);
237 /* at this point, we've adjusted the server state, so do the ping and
243 /* also, run the GC function for connections on all of the
244 * server's connections.
246 cm_GCConnections(tsp);
248 lock_ObtainWrite(&cm_serverLock);
249 cm_PutServerNoLock(tsp);
251 lock_ReleaseWrite(&cm_serverLock);
253 #else /* MULTI_CHECKSERVERS */
254 void cm_CheckServers(afs_uint32 flags, cm_cell_t *cellp)
257 * The goal of this function is to probe simultaneously
258 * probe all of the up/down servers (vldb/file) as
259 * specified by flags in the minimum number of RPCs.
260 * Effectively that means use one multi_RXAFS_GetCapabilities()
261 * followed by possibly one multi_RXAFS_GetTime() and
262 * one multi_VL_ProbeServer().
264 * To make this work we must construct the list of vldb
265 * and file servers that are to be probed as well as the
266 * associated data structures.
269 int srvAddrCount = 0;
270 struct srvAddr **addrs = NULL;
271 cm_conn_t **conns = NULL;
272 struct rx_connection **rxconns = NULL;
274 afs_int32 i, j, nconns = 0;
275 afs_int32 *conntimer, *results;
276 Capabilities *caps = NULL;
277 cm_server_t ** serversp, *tsp;
278 afs_uint32 isDown, wasDown;
280 time_t start, end, *deltas;
287 j = max(cm_numFileServers,cm_numVldbServers);
288 conns = (cm_conn_t **)malloc(j * sizeof(cm_conn_t *));
289 rxconns = (struct rx_connection **)malloc(j * sizeof(struct rx_connection *));
290 conntimer = (afs_int32 *)malloc(j * sizeof (afs_int32));
291 deltas = (time_t *)malloc(j * sizeof (time_t));
292 results = (afs_int32 *)malloc(j * sizeof (afs_int32));
293 serversp = (cm_server_t **)malloc(j * sizeof(cm_server_t *));
294 caps = (Capabilities *)malloc(j * sizeof(Capabilities));
296 memset(caps, 0, j * sizeof(Capabilities));
298 if ((flags & CM_FLAG_CHECKFILESERVERS) ||
299 !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
301 lock_ObtainWrite(&cm_serverLock);
303 for (nconns=0, tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
304 if (tsp->type != CM_SERVER_FILE ||
305 tsp->cellp == NULL || /* SetPref only */
306 cellp && cellp != tsp->cellp)
309 cm_GetServerNoLock(tsp);
310 lock_ReleaseWrite(&cm_serverLock);
312 lock_ObtainMutex(&tsp->mx);
313 isDown = tsp->flags & CM_SERVERFLAG_DOWN;
315 if ((tsp->flags & CM_SERVERFLAG_PINGING) ||
316 !((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
317 (!isDown && (flags & CM_FLAG_CHECKUPSERVERS)))) {
318 lock_ReleaseMutex(&tsp->mx);
319 lock_ObtainWrite(&cm_serverLock);
323 tsp->flags |= CM_SERVERFLAG_PINGING;
324 lock_ReleaseMutex(&tsp->mx);
326 serversp[nconns] = tsp;
327 code = cm_ConnByServer(tsp, cm_rootUserp, &conns[nconns]);
329 lock_ObtainWrite(&cm_serverLock);
330 cm_PutServerNoLock(tsp);
333 lock_ObtainWrite(&cm_serverLock);
334 rxconns[nconns] = cm_GetRxConn(conns[nconns]);
335 if (conntimer[nconns] = (isDown ? 1 : 0))
336 rx_SetConnDeadTime(rxconns[nconns], 10);
340 lock_ReleaseWrite(&cm_serverLock);
342 /* Perform the multi call */
344 multi_Rx(rxconns,nconns)
346 multi_RXAFS_GetCapabilities(&caps[multi_i]);
347 results[multi_i]=multi_error;
351 /* Process results of servers that support RXAFS_GetCapabilities */
352 for (i=0; i<nconns; i++) {
353 /* Leave the servers that did not support GetCapabilities alone */
354 if (results[i] == RXGEN_OPCODE)
358 rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
359 rx_PutConnection(rxconns[i]);
360 cm_PutConn(conns[i]);
363 cm_GCConnections(tsp);
365 lock_ObtainMutex(&tsp->mx);
366 wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
368 if (results[i] >= 0) {
369 /* mark server as up */
370 tsp->flags &= ~CM_SERVERFLAG_DOWN;
373 /* we currently handle 32-bits of capabilities */
374 if (caps[i].Capabilities_len > 0) {
375 tsp->capabilities = caps[i].Capabilities_val[0];
376 free(caps[i].Capabilities_val);
377 caps[i].Capabilities_len = 0;
378 caps[i].Capabilities_val = 0;
380 tsp->capabilities = 0;
383 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
384 osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is up with caps 0x%x",
385 osi_LogSaveString(afsd_logp, hoststr),
386 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
389 /* Now update the volume status if necessary */
391 cm_server_vols_t * tsrvp;
395 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
396 for (i=0; i<NUM_SERVER_VOLS; i++) {
397 if (tsrvp->ids[i] != 0) {
400 lock_ReleaseMutex(&tsp->mx);
401 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
402 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
403 lock_ObtainMutex(&tsp->mx);
405 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
413 /* mark server as down */
414 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
415 tsp->flags |= CM_SERVERFLAG_DOWN;
416 tsp->downTime = time(NULL);
418 if (code != VRESTARTING)
419 cm_ForceNewConnections(tsp);
421 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
422 osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
423 osi_LogSaveString(afsd_logp, hoststr),
424 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
427 /* Now update the volume status if necessary */
429 cm_server_vols_t * tsrvp;
433 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
434 for (i=0; i<NUM_SERVER_VOLS; i++) {
435 if (tsrvp->ids[i] != 0) {
438 lock_ReleaseMutex(&tsp->mx);
439 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
440 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
441 lock_ObtainMutex(&tsp->mx);
443 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
452 if (tsp->waitCount == 0)
453 tsp->flags &= ~CM_SERVERFLAG_PINGING;
455 osi_Wakeup((LONG_PTR)tsp);
457 lock_ReleaseMutex(&tsp->mx);
463 * At this point we have handled any responses that did not indicate
464 * that RXAFS_GetCapabilities is not supported.
466 for ( i=0, j=0; i<nconns; i++) {
467 if (results[i] == RXGEN_OPCODE) {
470 rxconns[j] = rxconns[i];
471 serversp[j] = serversp[i];
478 /* Perform the multi call */
480 multi_Rx(rxconns,nconns)
483 multi_RXAFS_GetTime(&secs, &usecs);
485 results[multi_i]=multi_error;
486 if ((start == end) && !multi_error)
487 deltas[multi_i] = end - secs;
491 /* Process Results of servers that only support RXAFS_GetTime */
492 for (i=0; i<nconns; i++) {
493 /* Leave the servers that did not support GetCapabilities alone */
495 rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
496 rx_PutConnection(rxconns[i]);
497 cm_PutConn(conns[i]);
500 cm_GCConnections(tsp);
502 lock_ObtainMutex(&tsp->mx);
503 wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
505 if (results[i] >= 0) {
506 /* mark server as up */
507 tsp->flags &= ~CM_SERVERFLAG_DOWN;
509 tsp->capabilities = 0;
511 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
512 osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is up with caps 0x%x",
513 osi_LogSaveString(afsd_logp, hoststr),
514 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
517 /* Now update the volume status if necessary */
519 cm_server_vols_t * tsrvp;
523 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
524 for (i=0; i<NUM_SERVER_VOLS; i++) {
525 if (tsrvp->ids[i] != 0) {
528 lock_ReleaseMutex(&tsp->mx);
529 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
530 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
531 lock_ObtainMutex(&tsp->mx);
533 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
541 /* mark server as down */
542 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
543 tsp->flags |= CM_SERVERFLAG_DOWN;
544 tsp->downTime = time(NULL);
546 if (code != VRESTARTING)
547 cm_ForceNewConnections(tsp);
549 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
550 osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
551 osi_LogSaveString(afsd_logp, hoststr),
552 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
555 /* Now update the volume status if necessary */
557 cm_server_vols_t * tsrvp;
561 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
562 for (i=0; i<NUM_SERVER_VOLS; i++) {
563 if (tsrvp->ids[i] != 0) {
566 lock_ReleaseMutex(&tsp->mx);
567 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
568 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
569 lock_ObtainMutex(&tsp->mx);
571 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
580 if (tsp->waitCount == 0)
581 tsp->flags &= ~CM_SERVERFLAG_PINGING;
583 osi_Wakeup((LONG_PTR)tsp);
585 lock_ReleaseMutex(&tsp->mx);
591 if ((flags & CM_FLAG_CHECKVLDBSERVERS) ||
592 !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
594 lock_ObtainWrite(&cm_serverLock);
596 for (nconns=0, tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
597 if (tsp->type != CM_SERVER_VLDB ||
598 tsp->cellp == NULL || /* SetPref only */
599 cellp && cellp != tsp->cellp)
602 cm_GetServerNoLock(tsp);
603 lock_ReleaseWrite(&cm_serverLock);
605 lock_ObtainMutex(&tsp->mx);
606 isDown = tsp->flags & CM_SERVERFLAG_DOWN;
608 if ((tsp->flags & CM_SERVERFLAG_PINGING) ||
609 !((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
610 (!isDown && (flags & CM_FLAG_CHECKUPSERVERS)))) {
611 lock_ReleaseMutex(&tsp->mx);
612 lock_ObtainWrite(&cm_serverLock);
616 tsp->flags |= CM_SERVERFLAG_PINGING;
617 lock_ReleaseMutex(&tsp->mx);
619 serversp[nconns] = tsp;
620 code = cm_ConnByServer(tsp, cm_rootUserp, &conns[nconns]);
622 lock_ObtainWrite(&cm_serverLock);
623 cm_PutServerNoLock(tsp);
626 lock_ObtainWrite(&cm_serverLock);
627 rxconns[nconns] = cm_GetRxConn(conns[nconns]);
628 conntimer[nconns] = (isDown ? 1 : 0);
630 rx_SetConnDeadTime(rxconns[nconns], 10);
634 lock_ReleaseWrite(&cm_serverLock);
636 /* Perform the multi call */
638 multi_Rx(rxconns,nconns)
640 multi_VL_ProbeServer();
641 results[multi_i]=multi_error;
645 /* Process results of servers that support RXAFS_GetCapabilities */
646 for (i=0; i<nconns; i++) {
648 rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
649 rx_PutConnection(rxconns[i]);
650 cm_PutConn(conns[i]);
653 cm_GCConnections(tsp);
655 lock_ObtainMutex(&tsp->mx);
656 wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
658 if (results[i] >= 0) {
659 /* mark server as up */
660 tsp->flags &= ~CM_SERVERFLAG_DOWN;
662 tsp->capabilities = 0;
664 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
665 osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is up with caps 0x%x",
666 osi_LogSaveString(afsd_logp, hoststr),
667 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
670 /* Now update the volume status if necessary */
672 cm_server_vols_t * tsrvp;
676 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
677 for (i=0; i<NUM_SERVER_VOLS; i++) {
678 if (tsrvp->ids[i] != 0) {
681 lock_ReleaseMutex(&tsp->mx);
682 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
683 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
684 lock_ObtainMutex(&tsp->mx);
686 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
694 /* mark server as down */
695 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
696 tsp->flags |= CM_SERVERFLAG_DOWN;
697 tsp->downTime = time(NULL);
699 if (code != VRESTARTING)
700 cm_ForceNewConnections(tsp);
702 afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
703 osi_Log3(afsd_logp, "cm_MultiPingServer server %s (%s) is down with caps 0x%x",
704 osi_LogSaveString(afsd_logp, hoststr),
705 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
708 /* Now update the volume status if necessary */
710 cm_server_vols_t * tsrvp;
714 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
715 for (i=0; i<NUM_SERVER_VOLS; i++) {
716 if (tsrvp->ids[i] != 0) {
719 lock_ReleaseMutex(&tsp->mx);
720 code = cm_GetVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
721 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
722 lock_ObtainMutex(&tsp->mx);
724 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
733 if (tsp->waitCount == 0)
734 tsp->flags &= ~CM_SERVERFLAG_PINGING;
736 osi_Wakeup((LONG_PTR)tsp);
738 lock_ReleaseMutex(&tsp->mx);
751 #endif /* MULTI_CHECKSERVERS */
753 void cm_InitServer(void)
755 static osi_once_t once;
757 if (osi_Once(&once)) {
758 lock_InitializeRWLock(&cm_serverLock, "cm_serverLock");
763 void cm_GetServer(cm_server_t *serverp)
765 lock_ObtainWrite(&cm_serverLock);
767 lock_ReleaseWrite(&cm_serverLock);
770 void cm_GetServerNoLock(cm_server_t *serverp)
775 void cm_PutServer(cm_server_t *serverp)
777 lock_ObtainWrite(&cm_serverLock);
778 osi_assertx(serverp->refCount-- > 0, "cm_server_t refCount 0");
779 lock_ReleaseWrite(&cm_serverLock);
782 void cm_PutServerNoLock(cm_server_t *serverp)
784 osi_assertx(serverp->refCount-- > 0, "cm_server_t refCount 0");
787 void cm_SetServerNo64Bit(cm_server_t * serverp, int no64bit)
789 lock_ObtainMutex(&serverp->mx);
791 serverp->flags |= CM_SERVERFLAG_NO64BIT;
793 serverp->flags &= ~CM_SERVERFLAG_NO64BIT;
794 lock_ReleaseMutex(&serverp->mx);
797 void cm_SetServerNoInlineBulk(cm_server_t * serverp, int no)
799 lock_ObtainMutex(&serverp->mx);
801 serverp->flags |= CM_SERVERFLAG_NOINLINEBULK;
803 serverp->flags &= ~CM_SERVERFLAG_NOINLINEBULK;
804 lock_ReleaseMutex(&serverp->mx);
807 void cm_SetServerPrefs(cm_server_t * serverp)
809 unsigned long serverAddr; /* in host byte order */
810 unsigned long myAddr, myNet, mySubnet;/* in host byte order */
811 unsigned long netMask;
814 int cm_noIPAddr; /* number of client network interfaces */
815 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
816 int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
817 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
818 int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */
821 /* get network related info */
822 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
823 code = syscfg_GetIFInfo(&cm_noIPAddr,
824 cm_IPAddr, cm_SubnetMask,
825 cm_NetMtu, cm_NetFlags);
827 serverAddr = ntohl(serverp->addr.sin_addr.s_addr);
828 serverp->ipRank = CM_IPRANK_LOW; /* default setings */
830 for ( i=0; i < cm_noIPAddr; i++)
832 /* loop through all the client's IP address and compare
833 ** each of them against the server's IP address */
835 myAddr = cm_IPAddr[i];
836 if ( IN_CLASSA(myAddr) )
837 netMask = IN_CLASSA_NET;
838 else if ( IN_CLASSB(myAddr) )
839 netMask = IN_CLASSB_NET;
840 else if ( IN_CLASSC(myAddr) )
841 netMask = IN_CLASSC_NET;
845 myNet = myAddr & netMask;
846 mySubnet = myAddr & cm_SubnetMask[i];
848 if ( (serverAddr & netMask) == myNet )
850 if ( (serverAddr & cm_SubnetMask[i]) == mySubnet)
852 if ( serverAddr == myAddr )
853 serverp->ipRank = min(serverp->ipRank,
854 CM_IPRANK_TOP);/* same machine */
855 else serverp->ipRank = min(serverp->ipRank,
856 CM_IPRANK_HI); /* same subnet */
858 else serverp->ipRank = min(serverp->ipRank,CM_IPRANK_MED);
861 /* random between 0..15*/
862 serverp->ipRank += min(serverp->ipRank, rand() % 0x000f);
863 } /* and of for loop */
866 cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cellp, afs_uint32 flags) {
869 osi_assertx(socketp->sin_family == AF_INET, "unexpected socket family");
871 tsp = malloc(sizeof(*tsp));
873 memset(tsp, 0, sizeof(*tsp));
877 lock_InitializeMutex(&tsp->mx, "cm_server_t mutex");
878 tsp->addr = *socketp;
880 cm_SetServerPrefs(tsp);
882 lock_ObtainWrite(&cm_serverLock); /* get server lock */
883 tsp->allNextp = cm_allServersp;
884 cm_allServersp = tsp;
895 lock_ReleaseWrite(&cm_serverLock); /* release server lock */
897 if ( !(flags & CM_FLAG_NOPROBE) ) {
898 tsp->flags = CM_SERVERFLAG_DOWN; /* assume down; ping will mark up if available */
899 cm_PingServer(tsp); /* Obtain Capabilities and check up/down state */
906 cm_FindServerByIP(afs_uint32 ipaddr, int type)
910 lock_ObtainRead(&cm_serverLock);
911 for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
912 if (tsp->type == type &&
913 tsp->addr.sin_addr.S_un.S_addr == ipaddr)
916 lock_ReleaseRead(&cm_serverLock);
921 /* find a server based on its properties */
922 cm_server_t *cm_FindServer(struct sockaddr_in *addrp, int type)
926 osi_assertx(addrp->sin_family == AF_INET, "unexpected socket value");
928 lock_ObtainWrite(&cm_serverLock);
929 for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
930 if (tsp->type == type &&
931 tsp->addr.sin_addr.s_addr == addrp->sin_addr.s_addr)
935 /* bump ref count if we found the server */
937 cm_GetServerNoLock(tsp);
939 /* drop big table lock */
940 lock_ReleaseWrite(&cm_serverLock);
942 /* return what we found */
946 cm_server_vols_t *cm_NewServerVols(void) {
947 cm_server_vols_t *tsvp;
949 tsvp = malloc(sizeof(*tsvp));
951 memset(tsvp, 0, sizeof(*tsvp));
956 cm_serverRef_t *cm_NewServerRef(cm_server_t *serverp, afs_uint32 volID)
958 cm_serverRef_t *tsrp;
959 cm_server_vols_t **tsrvpp = NULL;
960 afs_uint32 *slotp = NULL;
963 cm_GetServer(serverp);
964 tsrp = malloc(sizeof(*tsrp));
965 tsrp->server = serverp;
966 tsrp->status = srv_not_busy;
971 /* if we have a non-zero volID, we need to add it to the list
972 * of volumes maintained by the server. There are two phases:
973 * (1) see if the volID is already in the list and (2) insert
974 * it into the first empty slot if it is not.
977 lock_ObtainMutex(&serverp->mx);
979 tsrvpp = &serverp->vols;
983 for (i=0; i<NUM_SERVER_VOLS; i++) {
984 if ((*tsrvpp)->ids[i] == volID) {
987 } else if (!slotp && (*tsrvpp)->ids[i] == 0) {
988 slotp = &(*tsrvpp)->ids[i];
995 tsrvpp = &(*tsrvpp)->nextp;
1002 /* if we didn't find an empty slot in a current
1003 * page we must need a new page */
1004 *tsrvpp = cm_NewServerVols();
1006 (*tsrvpp)->ids[0] = volID;
1010 lock_ReleaseMutex(&serverp->mx);
1016 LONG_PTR cm_ChecksumServerList(cm_serverRef_t *serversp)
1020 cm_serverRef_t *tsrp;
1022 lock_ObtainWrite(&cm_serverLock);
1023 for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
1028 sum ^= (LONG_PTR) tsrp->server;
1031 lock_ReleaseWrite(&cm_serverLock);
1036 ** Insert a server into the server list keeping the list sorted in
1037 ** asending order of ipRank.
1039 ** The refCount of the cm_serverRef_t is increased
1041 void cm_InsertServerList(cm_serverRef_t** list, cm_serverRef_t* element)
1043 cm_serverRef_t *current=*list;
1044 unsigned short ipRank = element->server->ipRank;
1046 lock_ObtainWrite(&cm_serverLock);
1047 element->refCount++; /* increase refCount */
1049 /* insertion into empty list or at the beginning of the list */
1050 if ( !current || (current->server->ipRank > ipRank) )
1052 element->next = *list;
1054 lock_ReleaseWrite(&cm_serverLock);
1058 while ( current->next ) /* find appropriate place to insert */
1060 if ( current->next->server->ipRank > ipRank )
1062 else current = current->next;
1064 element->next = current->next;
1065 current->next = element;
1066 lock_ReleaseWrite(&cm_serverLock);
1069 ** Re-sort the server list with the modified rank
1070 ** returns 0 if element was changed successfully.
1071 ** returns 1 if list remained unchanged.
1073 long cm_ChangeRankServer(cm_serverRef_t** list, cm_server_t* server)
1075 cm_serverRef_t **current=list;
1076 cm_serverRef_t *element=0;
1078 /* if there is max of one element in the list, nothing to sort */
1079 if ( (!*current) || !((*current)->next) )
1080 return 1; /* list unchanged: return success */
1082 lock_ObtainWrite(&cm_serverLock);
1083 /* if the server is on the list, delete it from list */
1086 if ( (*current)->server == server)
1088 element = (*current);
1089 *current = (*current)->next; /* delete it */
1092 current = & ( (*current)->next);
1094 lock_ReleaseWrite(&cm_serverLock);
1096 /* if this volume is not replicated on this server */
1098 return 1; /* server is not on list */
1100 /* re-insert deleted element into the list with modified rank*/
1101 cm_InsertServerList(list, element);
1103 /* reduce refCount which was increased by cm_InsertServerList */
1104 lock_ObtainWrite(&cm_serverLock);
1105 element->refCount--;
1106 lock_ReleaseWrite(&cm_serverLock);
1110 ** If there are more than one server on the list and the first n servers on
1111 ** the list have the same rank( n>1), then randomise among the first n servers.
1113 void cm_RandomizeServer(cm_serverRef_t** list)
1116 cm_serverRef_t* tsrp = *list, *lastTsrp;
1117 unsigned short lowestRank;
1119 /* an empty list or a list with only one element */
1120 if ( !tsrp || ! tsrp->next )
1123 lock_ObtainWrite(&cm_serverLock);
1125 /* count the number of servers with the lowest rank */
1126 lowestRank = tsrp->server->ipRank;
1127 for ( count=1, tsrp=tsrp->next; tsrp; tsrp=tsrp->next)
1129 if ( tsrp->server->ipRank != lowestRank)
1135 /* if there is only one server with the lowest rank, we are done */
1137 lock_ReleaseWrite(&cm_serverLock);
1141 picked = rand() % count;
1143 lock_ReleaseWrite(&cm_serverLock);
1148 while (--picked >= 0)
1153 lastTsrp->next = tsrp->next; /* delete random element from list*/
1154 tsrp->next = *list; /* insert element at the beginning of list */
1156 lock_ReleaseWrite(&cm_serverLock);
1159 /* call cm_FreeServer while holding a write lock on cm_serverLock */
1160 void cm_FreeServer(cm_server_t* serverp)
1162 cm_server_vols_t * tsrvp, *nextp;
1164 cm_PutServerNoLock(serverp);
1165 if (serverp->refCount == 0)
1167 /* we need to check to ensure that all of the connections
1168 * for this server have a 0 refCount; otherwise, they will
1169 * not be garbage collected
1171 cm_GCConnections(serverp); /* connsp */
1173 if (!(serverp->flags & CM_SERVERFLAG_PREF_SET)) {
1174 switch (serverp->type) {
1175 case CM_SERVER_VLDB:
1176 cm_numVldbServers--;
1178 case CM_SERVER_FILE:
1179 cm_numFileServers--;
1183 lock_FinalizeMutex(&serverp->mx);
1184 if ( cm_allServersp == serverp )
1185 cm_allServersp = serverp->allNextp;
1189 for(tsp = cm_allServersp; tsp->allNextp; tsp=tsp->allNextp) {
1190 if ( tsp->allNextp == serverp ) {
1191 tsp->allNextp = serverp->allNextp;
1197 /* free the volid list */
1198 for ( tsrvp = serverp->vols; tsrvp; tsrvp = nextp) {
1199 nextp = tsrvp->nextp;
1208 void cm_RemoveVolumeFromServer(cm_server_t * serverp, afs_uint32 volID)
1210 cm_server_vols_t * tsrvp;
1216 for (tsrvp = serverp->vols; tsrvp; tsrvp = tsrvp->nextp) {
1217 for (i=0; i<NUM_SERVER_VOLS; i++) {
1218 if (tsrvp->ids[i] == volID) {
1226 void cm_FreeServerList(cm_serverRef_t** list, afs_uint32 flags)
1228 cm_serverRef_t **current = list;
1229 cm_serverRef_t **nextp = 0;
1230 cm_serverRef_t * next = 0;
1232 lock_ObtainWrite(&cm_serverLock);
1236 nextp = &(*current)->next;
1237 if (--((*current)->refCount) == 0) {
1240 if ((*current)->volID)
1241 cm_RemoveVolumeFromServer((*current)->server, (*current)->volID);
1242 cm_FreeServer((*current)->server);
1246 if (flags & CM_FREESERVERLIST_DELETE) {
1247 (*current)->status = srv_deleted;
1248 if ((*current)->volID)
1249 cm_RemoveVolumeFromServer((*current)->server, (*current)->volID);
1255 lock_ReleaseWrite(&cm_serverLock);