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 "../afs/param.h" /* Should be always first */
14 #include "../afs/stds.h"
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
19 #include <netinet/in.h>
22 #include "../h/hashing.h"
24 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV)
25 #include <netinet/in_var.h>
26 #endif /* ! ASF_HPUX110_ENV */
27 #endif /* !defined(UKERNEL) */
29 #include "../afs/afsincludes.h" /* Afs-based standard headers */
30 #include "../afs/afs_stats.h" /* afs statistics */
32 #if defined(AFS_SUN56_ENV)
34 #include <inet/common.h>
35 #if defined(AFS_SUN58_ENV)
36 #include <netinet/ip6.h>
41 /* Exported variables */
42 afs_rwlock_t afs_xcell; /* allocation lock for cells */
44 afs_int32 afs_cellindex=0;
45 afs_uint32 afs_nextCellNum = 0x100;
48 /* Local variables. */
49 struct cell *afs_rootcell = 0;
51 static char afs_AfsdbHandlerWait;
52 static char afs_AfsdbLookupWait;
54 char afs_AfsdbHandlerPresent = 0;
55 char afs_AfsdbHandlerInuse = 0;
57 char *afs_AfsdbHandler_CellName;
58 afs_int32 *afs_AfsdbHandler_CellHosts;
59 int *afs_AfsdbHandler_Timeout;
61 char afs_AfsdbHandler_ReqPending;
62 char afs_AfsdbHandler_Completed;
65 struct cell *afs_GetCellByName_int();
67 int afs_strcasecmp(s1, s2)
68 register char *s1, *s2;
75 if (c1 >= 'A' && c1 <= 'Z') c1 += 0x20;
76 if (c2 >= 'A' && c2 <= 'Z') c2 += 0x20;
86 int afs_AfsdbHandler(acellName, acellNameLen, kernelMsg)
91 /* afs_syscall_call() has already grabbed the global lock */
93 afs_AfsdbHandlerPresent = 1;
95 if (afs_AfsdbHandler_ReqPending) {
98 hostCount = kernelMsg[0];
99 *afs_AfsdbHandler_Timeout = kernelMsg[1];
100 if (*afs_AfsdbHandler_Timeout) *afs_AfsdbHandler_Timeout += osi_Time();
102 for (i=0; i<MAXCELLHOSTS; i++) {
104 afs_AfsdbHandler_CellHosts[i] = 0;
106 afs_AfsdbHandler_CellHosts[i] = kernelMsg[2+i];
109 /* Request completed, wake up the relevant thread */
110 afs_AfsdbHandler_ReqPending = 0;
111 afs_AfsdbHandler_Completed = 1;
112 afs_osi_Wakeup(&afs_AfsdbLookupWait);
115 /* Wait for a request */
116 while (afs_AfsdbHandler_ReqPending == 0)
117 afs_osi_Sleep(&afs_AfsdbHandlerWait);
119 /* Copy the requested cell name into the request buffer */
120 strncpy(acellName, afs_AfsdbHandler_CellName, acellNameLen);
122 /* Return the lookup request to userspace */
128 int afs_GetCellHostsFromDns(acellName, acellHosts, timeout)
130 afs_int32 *acellHosts;
136 if (!afs_AfsdbHandlerPresent) return ENOENT;
138 if (!ISAFS_GLOCK()) {
143 /* Wait until the AFSDB handler is available, and grab it */
144 while (afs_AfsdbHandlerInuse)
145 afs_osi_Sleep(&afs_AfsdbLookupWait);
146 afs_AfsdbHandlerInuse = 1;
148 /* Set up parameters for the handler */
149 afs_AfsdbHandler_CellName = acellName;
150 afs_AfsdbHandler_CellHosts = acellHosts;
151 afs_AfsdbHandler_Timeout = timeout;
153 /* Wake up the AFSDB handler */
154 afs_AfsdbHandler_Completed = 0;
155 afs_AfsdbHandler_ReqPending = 1;
156 afs_osi_Wakeup(&afs_AfsdbHandlerWait);
158 /* Wait for the handler to get back to us with the reply */
159 while (!afs_AfsdbHandler_Completed)
160 afs_osi_Sleep(&afs_AfsdbLookupWait);
162 /* Release the AFSDB handler and wake up others waiting for it */
163 afs_AfsdbHandlerInuse = 0;
164 afs_osi_Wakeup(&afs_AfsdbLookupWait);
166 if (grab_glock) AFS_GUNLOCK();
168 if (*acellHosts) return 0;
176 void afs_RefreshCell(tc)
177 register struct cell *tc;
179 afs_int32 acellHosts[MAXCELLHOSTS];
182 /* Don't need to do anything if no timeout or it's not expired */
183 if (!tc->timeout || tc->timeout > osi_Time()) return;
185 if (!afs_GetCellHostsFromDns(tc->cellName, acellHosts, &timeout)) {
186 afs_NewCell(tc->cellName, acellHosts, tc->states,
187 tc->lcellp ? tc->lcellp->cellName : (char *) 0,
188 tc->fsport, tc->vlport, timeout);
191 /* In case of a DNS failure, keep old cell data.. */
196 struct cell *afs_GetCellByName_Dns(acellName, locktype)
197 register char *acellName;
200 afs_int32 acellHosts[MAXCELLHOSTS];
203 if (afs_GetCellHostsFromDns(acellName, acellHosts, &timeout))
204 return (struct cell *) 0;
205 if (afs_NewCell(acellName, acellHosts, CNoSUID, (char *) 0, 0, 0, timeout))
206 return (struct cell *) 0;
208 return afs_GetCellByName_int(acellName, locktype, 0);
212 struct cell *afs_GetCellByName_int(acellName, locktype, trydns)
213 register char *acellName;
217 register struct cell *tc;
218 register struct afs_q *cq, *tq;
220 AFS_STATCNT(afs_GetCellByName);
221 ObtainWriteLock(&afs_xcell,100);
222 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
223 tc = QTOC(cq); tq = QNext(cq);
224 if (!afs_strcasecmp(tc->cellName, acellName)) {
226 QAdd(&CellLRU, &tc->lruq);
227 ReleaseWriteLock(&afs_xcell);
232 ReleaseWriteLock(&afs_xcell);
233 return trydns ? afs_GetCellByName_Dns(acellName, locktype)
236 } /*afs_GetCellByName_int*/
239 struct cell *afs_GetCellByName(acellName, locktype)
240 register char *acellName;
243 return afs_GetCellByName_int(acellName, locktype, 1);
245 } /*afs_GetCellByName*/
248 struct cell *afs_GetCell(acell, locktype)
249 register afs_int32 acell;
252 register struct cell *tc;
253 register struct afs_q *cq, *tq;
255 AFS_STATCNT(afs_GetCell);
256 if (acell == 1 && afs_rootcell) return afs_rootcell;
257 ObtainWriteLock(&afs_xcell,101);
258 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
259 tc = QTOC(cq); tq = QNext(cq);
260 if (tc->cell == acell) {
262 QAdd(&CellLRU, &tc->lruq);
263 ReleaseWriteLock(&afs_xcell);
268 ReleaseWriteLock(&afs_xcell);
269 return (struct cell *) 0;
274 struct cell *afs_GetCellByIndex(cellindex, locktype)
275 register afs_int32 cellindex;
278 register struct cell *tc;
279 register struct afs_q *cq, *tq;
281 AFS_STATCNT(afs_GetCellByIndex);
282 ObtainWriteLock(&afs_xcell,102);
283 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
284 tc = QTOC(cq); tq = QNext(cq);
285 if (tc->cellIndex == cellindex) {
287 QAdd(&CellLRU, &tc->lruq);
288 ReleaseWriteLock(&afs_xcell);
293 ReleaseWriteLock(&afs_xcell);
294 return (struct cell *) 0;
296 } /*afs_GetCellByIndex*/
299 afs_int32 afs_NewCell(acellName, acellHosts, aflags, linkedcname, fsport, vlport, timeout)
302 register afs_int32 *acellHosts;
304 u_short fsport, vlport;
307 register struct cell *tc, *tcl=0;
308 register afs_int32 i, newc=0, code=0;
309 register struct afs_q *cq, *tq;
311 AFS_STATCNT(afs_NewCell);
312 if (*acellHosts == 0)
313 /* need >= one host to gen cell # */
316 ObtainWriteLock(&afs_xcell,103);
318 /* Find the cell and mark its servers as not down but gone */
319 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
320 tc = QTOC(cq); tq = QNext(cq);
321 if (afs_strcasecmp(tc->cellName, acellName) == 0) {
322 /* we don't want to keep pinging old vlservers which were down,
323 * since they don't matter any more. It's easier to do this than
324 * to remove the server from its various hash tables. */
325 for (i=0; i<MAXCELLHOSTS; i++) {
326 if (!tc->cellHosts[i]) break;
327 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
328 tc->cellHosts[i]->flags |= SRVR_ISGONE;
334 if (cq != &CellLRU) {
338 tc = (struct cell *) afs_osi_Alloc(sizeof(struct cell));
339 QAdd(&CellLRU, &tc->lruq); /* put in lruq */
340 tc->cellName = (char *) afs_osi_Alloc(strlen(acellName)+1);
341 strcpy(tc->cellName, acellName);
342 tc->cellIndex = afs_cellindex++;
343 if (aflags & CPrimary) {
344 extern int afs_rootCellIndex;
345 tc->cell = 1; /* primary cell is always 1 */
347 afs_rootCellIndex = tc->cellIndex;
349 tc->cell = afs_nextCellNum++;
352 tc->lcellp = (struct cell *)0;
353 tc->fsport = (fsport ? fsport : AFS_FSPORT);
354 tc->vlport = (vlport ? vlport : AFS_VLPORT);
355 afs_stats_cmperf.numCellsVisible++;
359 if (aflags & CLinkedCell) {
364 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
365 tcl = QTOC(cq); tq = QNext(cq);
366 if (!afs_strcasecmp(tcl->cellName, linkedcname)) {
375 if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
376 tcl->lcellp->lcellp = (struct cell *)0;
377 tcl->lcellp->states &= ~CLinkedCell;
382 tc->states |= aflags;
383 tc->timeout = timeout;
385 bzero((char *)tc->cellHosts, sizeof(tc->cellHosts));
386 for (i=0; i<MAXCELLHOSTS; i++) {
388 afs_uint32 temp = acellHosts[i];
390 ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, (afsUUID *)0, 0);
392 ts->flags &= ~SRVR_ISGONE;
393 tc->cellHosts[i] = ts;
394 afs_PutServer(ts, WRITE_LOCK);
396 afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
397 ReleaseWriteLock(&afs_xcell);
402 afs_osi_Free(tc->cellName, strlen(tc->cellName)+1);
403 afs_osi_Free((char *)tc, sizeof(struct cell));
405 ReleaseWriteLock(&afs_xcell);
410 afs_RemoveCellEntry(struct server *srvp)
418 /* Remove the server structure from the cell list - if there */
419 ObtainWriteLock(&afs_xcell,200);
420 for (j=k=0; j<MAXCELLHOSTS; j++) {
421 if (!tc->cellHosts[j]) break;
422 if (tc->cellHosts[j] != srvp) {
423 tc->cellHosts[k++] = tc->cellHosts[j];
427 /* What do we do if we remove the last one? */
429 for (; k<MAXCELLHOSTS; k++) {
430 tc->cellHosts[k] = 0;
432 ReleaseWriteLock(&afs_xcell);