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
13 #include <afsconfig.h>
14 #include "../afs/param.h"
18 #include "../afs/stds.h"
19 #include "../afs/sysincludes.h" /* Standard vendor system headers */
23 #include <netinet/in.h>
26 #include "../h/hashing.h"
28 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV)
29 #include <netinet/in_var.h>
30 #endif /* ! ASF_HPUX110_ENV */
31 #endif /* !defined(UKERNEL) */
33 #include "../afs/afsincludes.h" /* Afs-based standard headers */
34 #include "../afs/afs_stats.h" /* afs statistics */
36 #if defined(AFS_SUN56_ENV)
38 #include <inet/common.h>
39 #if defined(AFS_SUN58_ENV)
40 #include <netinet/ip6.h>
45 /* Exported variables */
46 afs_rwlock_t afs_xcell; /* allocation lock for cells */
48 afs_int32 afs_cellindex=0;
49 afs_uint32 afs_nextCellNum = 0x100;
52 /* Local variables. */
53 struct cell *afs_rootcell = 0;
55 static char afs_AfsdbHandlerWait;
56 static char afs_AfsdbLookupWait;
58 char afs_AfsdbHandlerPresent = 0;
59 char afs_AfsdbHandlerInuse = 0;
60 char afs_AfsdbHandlerShutdown = 0;
62 char *afs_AfsdbHandler_CellName;
63 afs_int32 *afs_AfsdbHandler_CellHosts;
64 int *afs_AfsdbHandler_Timeout;
66 char afs_AfsdbHandler_ReqPending;
67 char afs_AfsdbHandler_Completed;
70 struct cell *afs_GetCellByName_int();
72 int afs_strcasecmp(s1, s2)
73 register char *s1, *s2;
80 if (c1 >= 'A' && c1 <= 'Z') c1 += 0x20;
81 if (c2 >= 'A' && c2 <= 'Z') c2 += 0x20;
93 if (afs_AfsdbHandlerPresent) {
94 afs_osi_Wakeup(&afs_AfsdbHandlerWait);
96 afs_AfsdbHandlerShutdown = 1;
97 afs_termState = AFSOP_STOP_RXEVENT;
101 int afs_AfsdbHandler(acellName, acellNameLen, kernelMsg)
104 afs_int32 *kernelMsg;
106 /* afs_syscall_call() has already grabbed the global lock */
108 if (afs_AfsdbHandlerShutdown) return -2;
109 afs_AfsdbHandlerPresent = 1;
111 if (afs_AfsdbHandler_ReqPending) {
114 hostCount = kernelMsg[0];
115 *afs_AfsdbHandler_Timeout = kernelMsg[1];
116 if (*afs_AfsdbHandler_Timeout) *afs_AfsdbHandler_Timeout += osi_Time();
118 for (i=0; i<MAXCELLHOSTS; i++) {
120 afs_AfsdbHandler_CellHosts[i] = 0;
122 afs_AfsdbHandler_CellHosts[i] = kernelMsg[2+i];
125 /* Request completed, wake up the relevant thread */
126 afs_AfsdbHandler_ReqPending = 0;
127 afs_AfsdbHandler_Completed = 1;
128 afs_osi_Wakeup(&afs_AfsdbLookupWait);
131 /* Wait for a request */
132 while (afs_AfsdbHandler_ReqPending == 0 && afs_termState != AFSOP_STOP_AFSDB)
133 afs_osi_Sleep(&afs_AfsdbHandlerWait);
135 /* Check if we're shutting down */
136 if (afs_termState == AFSOP_STOP_AFSDB) {
137 /* Inform anyone waiting for us that we're going away */
138 afs_AfsdbHandlerShutdown = 1;
139 afs_AfsdbHandlerPresent = 0;
140 afs_osi_Wakeup(&afs_AfsdbLookupWait);
142 afs_termState = AFSOP_STOP_RXEVENT;
143 afs_osi_Wakeup(&afs_termState);
147 /* Copy the requested cell name into the request buffer */
148 strncpy(acellName, afs_AfsdbHandler_CellName, acellNameLen);
150 /* Return the lookup request to userspace */
156 int afs_GetCellHostsFromDns(acellName, acellHosts, timeout)
158 afs_int32 *acellHosts;
164 if (!afs_AfsdbHandlerPresent) return ENOENT;
166 /* Initialize host list to empty in case the handler is gone */
169 if (!ISAFS_GLOCK()) {
174 /* Wait until the AFSDB handler is available, and grab it */
175 while (afs_AfsdbHandlerInuse)
176 afs_osi_Sleep(&afs_AfsdbLookupWait);
177 afs_AfsdbHandlerInuse = 1;
179 /* Set up parameters for the handler */
180 afs_AfsdbHandler_CellName = acellName;
181 afs_AfsdbHandler_CellHosts = acellHosts;
182 afs_AfsdbHandler_Timeout = timeout;
184 /* Wake up the AFSDB handler */
185 afs_AfsdbHandler_Completed = 0;
186 afs_AfsdbHandler_ReqPending = 1;
187 afs_osi_Wakeup(&afs_AfsdbHandlerWait);
189 /* Wait for the handler to get back to us with the reply */
190 while (afs_AfsdbHandlerPresent && !afs_AfsdbHandler_Completed)
191 afs_osi_Sleep(&afs_AfsdbLookupWait);
193 /* Release the AFSDB handler and wake up others waiting for it */
194 afs_AfsdbHandlerInuse = 0;
195 afs_osi_Wakeup(&afs_AfsdbLookupWait);
197 if (grab_glock) AFS_GUNLOCK();
199 if (*acellHosts) return 0;
207 void afs_RefreshCell(tc)
208 register struct cell *tc;
210 afs_int32 acellHosts[MAXCELLHOSTS];
213 /* Don't need to do anything if no timeout or it's not expired */
214 if (!tc->timeout || tc->timeout > osi_Time()) return;
216 if (!afs_GetCellHostsFromDns(tc->cellName, acellHosts, &timeout)) {
217 afs_NewCell(tc->cellName, acellHosts, tc->states,
218 tc->lcellp ? tc->lcellp->cellName : (char *) 0,
219 tc->fsport, tc->vlport, timeout);
222 /* In case of a DNS failure, keep old cell data.. */
227 struct cell *afs_GetCellByName_Dns(acellName, locktype)
228 register char *acellName;
231 afs_int32 acellHosts[MAXCELLHOSTS];
234 if (afs_GetCellHostsFromDns(acellName, acellHosts, &timeout))
235 return (struct cell *) 0;
236 if (afs_NewCell(acellName, acellHosts, CNoSUID, (char *) 0, 0, 0, timeout))
237 return (struct cell *) 0;
239 return afs_GetCellByName_int(acellName, locktype, 0);
243 struct cell *afs_GetCellByName_int(acellName, locktype, trydns)
244 register char *acellName;
248 register struct cell *tc;
249 register struct afs_q *cq, *tq;
251 AFS_STATCNT(afs_GetCellByName);
252 ObtainWriteLock(&afs_xcell,100);
253 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
254 tc = QTOC(cq); tq = QNext(cq);
255 if (!afs_strcasecmp(tc->cellName, acellName)) {
257 QAdd(&CellLRU, &tc->lruq);
258 ReleaseWriteLock(&afs_xcell);
263 ReleaseWriteLock(&afs_xcell);
264 return trydns ? afs_GetCellByName_Dns(acellName, locktype)
267 } /*afs_GetCellByName_int*/
270 struct cell *afs_GetCellByName(acellName, locktype)
271 register char *acellName;
274 return afs_GetCellByName_int(acellName, locktype, 1);
276 } /*afs_GetCellByName*/
279 struct cell *afs_GetCell(acell, locktype)
280 register afs_int32 acell;
283 register struct cell *tc;
284 register struct afs_q *cq, *tq;
286 AFS_STATCNT(afs_GetCell);
287 if (acell == 1 && afs_rootcell) return afs_rootcell;
288 ObtainWriteLock(&afs_xcell,101);
289 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
290 tc = QTOC(cq); tq = QNext(cq);
291 if (tc->cell == acell) {
293 QAdd(&CellLRU, &tc->lruq);
294 ReleaseWriteLock(&afs_xcell);
299 ReleaseWriteLock(&afs_xcell);
300 return (struct cell *) 0;
305 struct cell *afs_GetCellByIndex(cellindex, locktype)
306 register afs_int32 cellindex;
309 register struct cell *tc;
310 register struct afs_q *cq, *tq;
312 AFS_STATCNT(afs_GetCellByIndex);
313 ObtainWriteLock(&afs_xcell,102);
314 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
315 tc = QTOC(cq); tq = QNext(cq);
316 if (tc->cellIndex == cellindex) {
318 QAdd(&CellLRU, &tc->lruq);
319 ReleaseWriteLock(&afs_xcell);
324 ReleaseWriteLock(&afs_xcell);
325 return (struct cell *) 0;
327 } /*afs_GetCellByIndex*/
330 afs_int32 afs_NewCell(acellName, acellHosts, aflags, linkedcname, fsport, vlport, timeout)
333 register afs_int32 *acellHosts;
335 u_short fsport, vlport;
338 register struct cell *tc, *tcl=0;
339 register afs_int32 i, newc=0, code=0;
340 register struct afs_q *cq, *tq;
342 AFS_STATCNT(afs_NewCell);
343 if (*acellHosts == 0)
344 /* need >= one host to gen cell # */
347 ObtainWriteLock(&afs_xcell,103);
349 /* Find the cell and mark its servers as not down but gone */
350 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
351 tc = QTOC(cq); tq = QNext(cq);
352 if (afs_strcasecmp(tc->cellName, acellName) == 0) {
353 /* we don't want to keep pinging old vlservers which were down,
354 * since they don't matter any more. It's easier to do this than
355 * to remove the server from its various hash tables. */
356 for (i=0; i<MAXCELLHOSTS; i++) {
357 if (!tc->cellHosts[i]) break;
358 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
359 tc->cellHosts[i]->flags |= SRVR_ISGONE;
365 if (cq != &CellLRU) {
369 tc = (struct cell *) afs_osi_Alloc(sizeof(struct cell));
370 QAdd(&CellLRU, &tc->lruq); /* put in lruq */
371 tc->cellName = (char *) afs_osi_Alloc(strlen(acellName)+1);
372 strcpy(tc->cellName, acellName);
373 tc->cellIndex = afs_cellindex++;
374 if (aflags & CPrimary) {
375 extern int afs_rootCellIndex;
376 tc->cell = 1; /* primary cell is always 1 */
378 afs_rootCellIndex = tc->cellIndex;
380 tc->cell = afs_nextCellNum++;
383 tc->lcellp = (struct cell *)0;
384 tc->fsport = (fsport ? fsport : AFS_FSPORT);
385 tc->vlport = (vlport ? vlport : AFS_VLPORT);
386 afs_stats_cmperf.numCellsVisible++;
390 if (aflags & CLinkedCell) {
395 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
396 tcl = QTOC(cq); tq = QNext(cq);
397 if (!afs_strcasecmp(tcl->cellName, linkedcname)) {
406 if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
407 tcl->lcellp->lcellp = (struct cell *)0;
408 tcl->lcellp->states &= ~CLinkedCell;
413 tc->states |= aflags;
414 tc->timeout = timeout;
416 memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts));
417 for (i=0; i<MAXCELLHOSTS; i++) {
419 afs_uint32 temp = acellHosts[i];
421 ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, (afsUUID *)0, 0);
423 ts->flags &= ~SRVR_ISGONE;
424 tc->cellHosts[i] = ts;
425 afs_PutServer(ts, WRITE_LOCK);
427 afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
428 ReleaseWriteLock(&afs_xcell);
433 afs_osi_Free(tc->cellName, strlen(tc->cellName)+1);
434 afs_osi_Free((char *)tc, sizeof(struct cell));
436 ReleaseWriteLock(&afs_xcell);
441 afs_RemoveCellEntry(struct server *srvp)
449 /* Remove the server structure from the cell list - if there */
450 ObtainWriteLock(&afs_xcell,200);
451 for (j=k=0; j<MAXCELLHOSTS; j++) {
452 if (!tc->cellHosts[j]) break;
453 if (tc->cellHosts[j] != srvp) {
454 tc->cellHosts[k++] = tc->cellHosts[j];
458 /* What do we do if we remove the last one? */
460 for (; k<MAXCELLHOSTS; k++) {
461 tc->cellHosts[k] = 0;
463 ReleaseWriteLock(&afs_xcell);