* SECURITY: Apply upstream patch to disable setuid status on all cells
[pkg-k5-afs_openafs.git] / src / afs / afs_cell.c
blob564c0be2e10ce13757a9ffdb0ea2f21db946fa3a
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
11 * Implements:
13 #include <afsconfig.h>
14 #include "afs/param.h"
16 RCSID
17 ("$Header: /cvs/openafs/src/afs/afs_cell.c,v 1.30.2.3 2005/09/23 14:56:26 shadow Exp $");
19 #include "afs/stds.h"
20 #include "afs/sysincludes.h" /* Standard vendor system headers */
21 #include "afsincludes.h" /* Afs-based standard headers */
22 #include "afs/afs_stats.h" /* afs statistics */
23 #include "afs/afs_osi.h"
25 /* Local variables. */
26 afs_rwlock_t afs_xcell; /* Export for cmdebug peeking at locks */
29 * AFSDB implementation:
31 * afs_StopAFSDB: terminate the AFSDB handler, used on shutdown
32 * afs_AFSDBHandler: entry point for user-space AFSDB request handler
33 * afs_GetCellHostsAFSDB: query the AFSDB handler and wait for response
34 * afs_LookupAFSDB: look up AFSDB for given cell name and create locally
37 #ifdef AFS_AFSDB_ENV
38 static afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
39 static char afsdb_handler_running; /* Protected by GLOCK */
40 static char afsdb_handler_shutdown; /* Protected by GLOCK */
42 static struct {
43 afs_rwlock_t lock;
44 char pending;
45 char complete;
46 char *cellname;
47 afs_int32 *cellhosts;
48 int *timeout;
49 char **realname;
50 } afsdb_req;
52 void
53 afs_StopAFSDB()
55 if (afsdb_handler_running) {
56 afs_osi_Wakeup(&afsdb_req);
57 } else {
58 afsdb_handler_shutdown = 1;
59 afs_termState = AFSOP_STOP_RXEVENT;
63 int
64 afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 * kernelMsg)
66 if (afsdb_handler_shutdown)
67 return -2;
68 afsdb_handler_running = 1;
70 ObtainSharedLock(&afsdb_req.lock, 683);
71 if (afsdb_req.pending) {
72 int i, hostCount;
74 UpgradeSToWLock(&afsdb_req.lock, 684);
75 hostCount = kernelMsg[0];
76 *afsdb_req.timeout = kernelMsg[1];
77 if (*afsdb_req.timeout)
78 *afsdb_req.timeout += osi_Time();
79 *afsdb_req.realname = afs_strdup(acellName);
81 for (i = 0; i < MAXCELLHOSTS; i++) {
82 if (i >= hostCount)
83 afsdb_req.cellhosts[i] = 0;
84 else
85 afsdb_req.cellhosts[i] = kernelMsg[2 + i];
88 /* Request completed, wake up the relevant thread */
89 afsdb_req.pending = 0;
90 afsdb_req.complete = 1;
91 afs_osi_Wakeup(&afsdb_req);
92 ConvertWToSLock(&afsdb_req.lock);
94 ConvertSToRLock(&afsdb_req.lock);
96 /* Wait for a request */
97 while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
98 ReleaseReadLock(&afsdb_req.lock);
99 afs_osi_Sleep(&afsdb_req);
100 ObtainReadLock(&afsdb_req.lock);
103 /* Check if we're shutting down */
104 if (afs_termState == AFSOP_STOP_AFSDB) {
105 ReleaseReadLock(&afsdb_req.lock);
107 /* Inform anyone waiting for us that we're going away */
108 afsdb_handler_shutdown = 1;
109 afsdb_handler_running = 0;
110 afs_osi_Wakeup(&afsdb_req);
112 afs_termState = AFSOP_STOP_RXEVENT;
113 afs_osi_Wakeup(&afs_termState);
114 return -2;
117 /* Return the lookup request to userspace */
118 strncpy(acellName, afsdb_req.cellname, acellNameLen);
119 ReleaseReadLock(&afsdb_req.lock);
120 return 0;
123 static int
124 afs_GetCellHostsAFSDB(char *acellName, afs_int32 * acellHosts, int *timeout,
125 char **realName)
127 AFS_ASSERT_GLOCK();
128 if (!afsdb_handler_running)
129 return ENOENT;
131 ObtainWriteLock(&afsdb_client_lock, 685);
132 ObtainWriteLock(&afsdb_req.lock, 686);
134 *acellHosts = 0;
135 afsdb_req.cellname = acellName;
136 afsdb_req.cellhosts = acellHosts;
137 afsdb_req.timeout = timeout;
138 afsdb_req.realname = realName;
140 afsdb_req.complete = 0;
141 afsdb_req.pending = 1;
142 afs_osi_Wakeup(&afsdb_req);
143 ConvertWToRLock(&afsdb_req.lock);
145 while (afsdb_handler_running && !afsdb_req.complete) {
146 ReleaseReadLock(&afsdb_req.lock);
147 afs_osi_Sleep(&afsdb_req);
148 ObtainReadLock(&afsdb_req.lock);
150 ReleaseReadLock(&afsdb_req.lock);
151 ReleaseWriteLock(&afsdb_client_lock);
153 if (*acellHosts)
154 return 0;
155 else
156 return ENOENT;
158 #endif
160 void
161 afs_LookupAFSDB(char *acellName)
163 #ifdef AFS_AFSDB_ENV
164 afs_int32 cellHosts[MAXCELLHOSTS];
165 char *realName = NULL;
166 int code, timeout;
168 code = afs_GetCellHostsAFSDB(acellName, cellHosts, &timeout, &realName);
169 if (code)
170 goto done;
171 code = afs_NewCell(realName, cellHosts, CNoSUID, NULL, 0, 0, timeout);
172 if (code && code != EEXIST)
173 goto done;
175 /* If we found an alias, create it */
176 if (afs_strcasecmp(acellName, realName))
177 afs_NewCellAlias(acellName, realName);
179 done:
180 if (realName)
181 afs_osi_FreeStr(realName);
182 #endif
186 * Cell name-to-ID mapping
188 * afs_cellname_new: create a new cell name, optional cell number
189 * afs_cellname_lookup_id: look up a cell name
190 * afs_cellname_lookup_name: look up a cell number
191 * afs_cellname_ref: note that this cell name was referenced somewhere
192 * afs_cellname_init: load the list of cells from given inode
193 * afs_cellname_write: write in-kernel list of cells to disk
196 struct cell_name *afs_cellname_head; /* Export for kdump */
197 static ino_t afs_cellname_inode;
198 static int afs_cellname_inode_set;
199 static int afs_cellname_dirty;
200 static afs_int32 afs_cellnum_next;
202 static struct cell_name *
203 afs_cellname_new(char *name, afs_int32 cellnum)
205 struct cell_name *cn;
207 if (cellnum == 0)
208 cellnum = afs_cellnum_next;
210 cn = (struct cell_name *)afs_osi_Alloc(sizeof(*cn));
211 cn->next = afs_cellname_head;
212 cn->cellnum = cellnum;
213 cn->cellname = afs_strdup(name);
214 cn->used = 0;
215 afs_cellname_head = cn;
217 if (cellnum >= afs_cellnum_next)
218 afs_cellnum_next = cellnum + 1;
220 return cn;
223 static struct cell_name *
224 afs_cellname_lookup_id(afs_int32 cellnum)
226 struct cell_name *cn;
228 for (cn = afs_cellname_head; cn; cn = cn->next)
229 if (cn->cellnum == cellnum)
230 return cn;
232 return NULL;
235 static struct cell_name *
236 afs_cellname_lookup_name(char *name)
238 struct cell_name *cn;
240 for (cn = afs_cellname_head; cn; cn = cn->next)
241 if (strcmp(cn->cellname, name) == 0)
242 return cn;
244 return NULL;
247 static void
248 afs_cellname_ref(struct cell_name *cn)
250 if (!cn->used) {
251 cn->used = 1;
252 afs_cellname_dirty = 1;
257 afs_cellname_init(ino_t inode, int lookupcode)
259 struct osi_file *tfile;
260 int cc, off = 0;
262 ObtainWriteLock(&afs_xcell, 692);
264 afs_cellnum_next = 1;
265 afs_cellname_dirty = 0;
267 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
268 ReleaseWriteLock(&afs_xcell);
269 return 0;
271 if (lookupcode) {
272 ReleaseWriteLock(&afs_xcell);
273 return lookupcode;
276 tfile = osi_UFSOpen(inode);
277 if (!tfile) {
278 ReleaseWriteLock(&afs_xcell);
279 return EIO;
282 afs_cellname_inode = inode;
283 afs_cellname_inode_set = 1;
285 while (1) {
286 afs_int32 cellnum, clen, magic;
287 struct cell_name *cn;
288 char *cellname;
290 cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
291 if (cc != sizeof(magic))
292 break;
293 if (magic != AFS_CELLINFO_MAGIC)
294 break;
295 off += cc;
297 cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
298 if (cc != sizeof(cellnum))
299 break;
300 off += cc;
302 cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
303 if (cc != sizeof(clen))
304 break;
305 off += cc;
307 cellname = afs_osi_Alloc(clen + 1);
308 if (!cellname)
309 break;
311 cc = afs_osi_Read(tfile, off, cellname, clen);
312 if (cc != clen) {
313 afs_osi_Free(cellname, clen + 1);
314 break;
316 off += cc;
317 cellname[clen] = '\0';
319 if (afs_cellname_lookup_name(cellname)
320 || afs_cellname_lookup_id(cellnum)) {
321 afs_osi_Free(cellname, clen + 1);
322 break;
325 cn = afs_cellname_new(cellname, cellnum);
326 afs_osi_Free(cellname, clen + 1);
329 osi_UFSClose(tfile);
330 ReleaseWriteLock(&afs_xcell);
331 return 0;
335 afs_cellname_write(void)
337 struct osi_file *tfile;
338 struct cell_name *cn;
339 int off;
341 if (!afs_cellname_dirty || !afs_cellname_inode_set)
342 return 0;
343 if (afs_initState != 300)
344 return 0;
346 ObtainWriteLock(&afs_xcell, 693);
347 afs_cellname_dirty = 0;
348 off = 0;
349 tfile = osi_UFSOpen(afs_cellname_inode);
350 if (!tfile) {
351 ReleaseWriteLock(&afs_xcell);
352 return EIO;
355 for (cn = afs_cellname_head; cn; cn = cn->next) {
356 afs_int32 magic, cellnum, clen;
357 int cc;
359 if (!cn->used)
360 continue;
362 magic = AFS_CELLINFO_MAGIC;
363 cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
364 if (cc != sizeof(magic))
365 break;
366 off += cc;
368 cellnum = cn->cellnum;
369 cc = afs_osi_Write(tfile, off, &cellnum, sizeof(cellnum));
370 if (cc != sizeof(cellnum))
371 break;
372 off += cc;
374 clen = strlen(cn->cellname);
375 cc = afs_osi_Write(tfile, off, &clen, sizeof(clen));
376 if (cc != sizeof(clen))
377 break;
378 off += cc;
380 cc = afs_osi_Write(tfile, off, cn->cellname, clen);
381 if (cc != clen)
382 break;
383 off += clen;
386 osi_UFSClose(tfile);
387 ReleaseWriteLock(&afs_xcell);
388 return 0;
392 * Cell alias implementation
394 * afs_FindCellAlias: look up cell alias by alias name
395 * afs_GetCellAlias: get cell alias by index (starting at 0)
396 * afs_PutCellAlias: put back a cell alias returned by Find or Get
397 * afs_NewCellAlias: create new cell alias entry
400 struct cell_alias *afs_cellalias_head; /* Export for kdump */
401 static afs_int32 afs_cellalias_index;
402 static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
404 static struct cell_alias *
405 afs_FindCellAlias(char *alias)
407 struct cell_alias *tc;
409 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
410 if (!strcmp(alias, tc->alias))
411 break;
412 return tc;
415 struct cell_alias *
416 afs_GetCellAlias(int index)
418 struct cell_alias *tc;
420 ObtainReadLock(&afs_xcell);
421 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
422 if (tc->index == index)
423 break;
424 ReleaseReadLock(&afs_xcell);
426 return tc;
429 void
430 afs_PutCellAlias(struct cell_alias *a)
432 return;
435 afs_int32
436 afs_NewCellAlias(char *alias, char *cell)
438 struct cell_alias *tc;
440 ObtainSharedLock(&afs_xcell, 681);
441 if (afs_CellOrAliasExists_nl(alias)) {
442 ReleaseSharedLock(&afs_xcell);
443 return EEXIST;
446 UpgradeSToWLock(&afs_xcell, 682);
447 tc = (struct cell_alias *)afs_osi_Alloc(sizeof(struct cell_alias));
448 tc->alias = afs_strdup(alias);
449 tc->cell = afs_strdup(cell);
450 tc->next = afs_cellalias_head;
451 tc->index = afs_cellalias_index++;
452 afs_cellalias_head = tc;
453 ReleaseWriteLock(&afs_xcell);
455 afs_DynrootInvalidate();
456 return 0;
460 * Actual cell list implementation
462 * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
463 * afs_RefreshCell: look up cell information in AFSDB if timeout expired
465 * afs_TraverseCells: execute a callback for each existing cell
466 * afs_TraverseCells_nl: same as above except without locking afs_xcell
467 * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
469 * afs_FindCellByName: return a cell with a given name, if it exists
470 * afs_FindCellByName_nl: same as above, without locking afs_xcell
471 * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
472 * afs_GetCell: return a cell with a given cell number
473 * afs_GetCellStale: same as GetCell, but does not try to refresh the data
474 * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
476 * afs_GetPrimaryCell: return the primary cell, if any
477 * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
478 * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
479 * afs_SetPrimaryCell: set the primary cell name to the given cell name
481 * afs_NewCell: create or update a cell entry
484 struct afs_q CellLRU; /* Export for kdump */
485 static char *afs_thiscell;
486 afs_int32 afs_cellindex; /* Export for kdump */
488 static void
489 afs_UpdateCellLRU(struct cell *c)
491 ObtainWriteLock(&afs_xcell, 100);
492 QRemove(&c->lruq);
493 QAdd(&CellLRU, &c->lruq);
494 ReleaseWriteLock(&afs_xcell);
497 static void
498 afs_RefreshCell(struct cell *ac)
500 if (ac->states & CNoAFSDB)
501 return;
502 if (!ac->cellHosts[0] || (ac->timeout && ac->timeout <= osi_Time()))
503 afs_LookupAFSDB(ac->cellName);
506 static void *
507 afs_TraverseCells_nl(void *(*cb) (struct cell *, void *), void *arg)
509 struct afs_q *cq, *tq;
510 struct cell *tc;
511 void *ret = NULL;
513 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
514 tc = QTOC(cq);
516 /* This is assuming that a NULL return is acceptable. */
517 if (cq) {
518 tq = QNext(cq);
519 } else {
520 return NULL;
523 ret = cb(tc, arg);
524 if (ret)
525 break;
528 return ret;
531 void *
532 afs_TraverseCells(void *(*cb) (struct cell *, void *), void *arg)
534 void *ret;
536 ObtainReadLock(&afs_xcell);
537 ret = afs_TraverseCells_nl(cb, arg);
538 ReleaseReadLock(&afs_xcell);
540 return ret;
543 static void *
544 afs_choose_cell_by_name(struct cell *cell, void *arg)
546 if (!arg) {
547 /* Safety net */
548 return cell;
549 } else {
550 return strcmp(cell->cellName, (char *)arg) ? NULL : cell;
554 static void *
555 afs_choose_cell_by_num(struct cell *cell, void *arg)
557 return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
560 static void *
561 afs_choose_cell_by_index(struct cell *cell, void *arg)
563 return (cell->cellIndex == *((afs_int32 *) arg)) ? cell : NULL;
566 static struct cell *
567 afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
569 return afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
572 static struct cell *
573 afs_FindCellByName(char *acellName, afs_int32 locktype)
575 return afs_TraverseCells(&afs_choose_cell_by_name, acellName);
578 struct cell *
579 afs_GetCellByName(char *acellName, afs_int32 locktype)
581 struct cell *tc;
583 tc = afs_FindCellByName(acellName, locktype);
584 if (!tc) {
585 afs_LookupAFSDB(acellName);
586 tc = afs_FindCellByName(acellName, locktype);
588 if (tc) {
589 afs_cellname_ref(tc->cnamep);
590 afs_UpdateCellLRU(tc);
591 afs_RefreshCell(tc);
594 return tc;
597 struct cell *
598 afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
600 struct cell *tc;
601 struct cell_name *cn;
603 tc = afs_GetCellStale(cellnum, locktype);
604 if (tc) {
605 afs_RefreshCell(tc);
606 } else {
607 ObtainReadLock(&afs_xcell);
608 cn = afs_cellname_lookup_id(cellnum);
609 ReleaseReadLock(&afs_xcell);
610 if (cn)
611 tc = afs_GetCellByName(cn->cellname, locktype);
613 return tc;
616 struct cell *
617 afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
619 struct cell *tc;
621 tc = afs_TraverseCells(&afs_choose_cell_by_num, &cellnum);
622 if (tc) {
623 afs_cellname_ref(tc->cnamep);
624 afs_UpdateCellLRU(tc);
626 return tc;
629 struct cell *
630 afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
632 struct cell *tc;
634 tc = afs_TraverseCells(&afs_choose_cell_by_index, &index);
635 if (tc)
636 afs_UpdateCellLRU(tc);
637 return tc;
640 struct cell *
641 afs_GetPrimaryCell(afs_int32 locktype)
643 return afs_GetCellByName(afs_thiscell, locktype);
647 afs_IsPrimaryCell(struct cell *cell)
649 /* Simple safe checking */
650 if (!cell) {
651 return 0;
652 } else if (!afs_thiscell) {
653 /* This is simply a safety net to avoid seg faults especially when
654 * using a user-space library. afs_SetPrimaryCell() should be set
655 * prior to this call. */
656 afs_SetPrimaryCell(cell->cellName);
657 return 1;
658 } else {
659 return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
664 afs_IsPrimaryCellNum(afs_int32 cellnum)
666 struct cell *tc;
667 int primary = 0;
669 tc = afs_GetCellStale(cellnum, READ_LOCK);
670 if (tc) {
671 primary = afs_IsPrimaryCell(tc);
672 afs_PutCell(tc, READ_LOCK);
675 return primary;
678 afs_int32
679 afs_SetPrimaryCell(char *acellName)
681 ObtainWriteLock(&afs_xcell, 691);
682 if (afs_thiscell)
683 afs_osi_FreeStr(afs_thiscell);
684 afs_thiscell = afs_strdup(acellName);
685 ReleaseWriteLock(&afs_xcell);
686 return 0;
689 afs_int32
690 afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
691 char *linkedcname, u_short fsport, u_short vlport, int timeout)
693 struct cell *tc, *tcl = 0;
694 afs_int32 i, newc = 0, code = 0;
696 AFS_STATCNT(afs_NewCell);
698 ObtainWriteLock(&afs_xcell, 103);
700 tc = afs_FindCellByName_nl(acellName, READ_LOCK);
701 if (tc) {
702 aflags &= ~CNoSUID;
703 } else {
704 tc = (struct cell *)afs_osi_Alloc(sizeof(struct cell));
705 memset((char *)tc, 0, sizeof(*tc));
706 tc->cellName = afs_strdup(acellName);
707 tc->fsport = AFS_FSPORT;
708 tc->vlport = AFS_VLPORT;
709 RWLOCK_INIT(&tc->lock, "cell lock");
710 newc = 1;
711 aflags |= CNoSUID;
713 ObtainWriteLock(&tc->lock, 688);
715 /* If the cell we've found has the correct name but no timeout,
716 * and we're called with a non-zero timeout, bail out: never
717 * override static configuration entries with AFSDB ones.
718 * One exception: if the original cell entry had no servers,
719 * it must get servers from AFSDB.
721 if (timeout && !tc->timeout && tc->cellHosts[0]) {
722 code = EEXIST; /* This code is checked for in afs_LookupAFSDB */
723 goto bad;
726 /* we don't want to keep pinging old vlservers which were down,
727 * since they don't matter any more. It's easier to do this than
728 * to remove the server from its various hash tables. */
729 for (i = 0; i < MAXCELLHOSTS; i++) {
730 if (!tc->cellHosts[i])
731 break;
732 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
733 tc->cellHosts[i]->flags |= SRVR_ISGONE;
736 if (fsport)
737 tc->fsport = fsport;
738 if (vlport)
739 tc->vlport = vlport;
741 if (aflags & CLinkedCell) {
742 if (!linkedcname) {
743 code = EINVAL;
744 goto bad;
746 tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
747 if (!tcl) {
748 code = ENOENT;
749 goto bad;
751 if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
752 tcl->lcellp->lcellp = (struct cell *)0;
753 tcl->lcellp->states &= ~CLinkedCell;
755 tc->lcellp = tcl;
756 tcl->lcellp = tc;
758 tc->states |= aflags;
759 tc->timeout = timeout;
761 memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts));
762 for (i = 0; i < MAXCELLHOSTS; i++) {
763 struct server *ts;
764 afs_uint32 temp = acellHosts[i];
765 if (!temp)
766 break;
767 ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
768 ts->cell = tc;
769 ts->flags &= ~SRVR_ISGONE;
770 tc->cellHosts[i] = ts;
771 afs_PutServer(ts, WRITE_LOCK);
773 afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
775 if (newc) {
776 struct cell_name *cn;
778 cn = afs_cellname_lookup_name(acellName);
779 if (!cn)
780 cn = afs_cellname_new(acellName, 0);
782 tc->cnamep = cn;
783 tc->cellNum = cn->cellnum;
784 tc->cellIndex = afs_cellindex++;
785 afs_stats_cmperf.numCellsVisible++;
786 QAdd(&CellLRU, &tc->lruq);
789 ReleaseWriteLock(&tc->lock);
790 ReleaseWriteLock(&afs_xcell);
791 afs_PutCell(tc, 0);
792 afs_DynrootInvalidate();
793 return 0;
795 bad:
796 if (newc) {
797 afs_osi_FreeStr(tc->cellName);
798 afs_osi_Free(tc, sizeof(struct cell));
800 ReleaseWriteLock(&tc->lock);
801 ReleaseWriteLock(&afs_xcell);
802 return code;
806 * Miscellaneous stuff
808 * afs_CellInit: perform whatever initialization is necessary
809 * shutdown_cell: called on shutdown, should deallocate memory, etc
810 * afs_RemoveCellEntry: remove a server from a cell's server list
811 * afs_CellOrAliasExists: check if the given name exists as a cell or alias
812 * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
813 * afs_CellNumValid: check if a cell number is valid (also set the used flag)
816 void
817 afs_CellInit()
819 RWLOCK_INIT(&afs_xcell, "afs_xcell");
820 #ifdef AFS_AFSDB_ENV
821 RWLOCK_INIT(&afsdb_client_lock, "afsdb_client_lock");
822 RWLOCK_INIT(&afsdb_req.lock, "afsdb_req.lock");
823 #endif
824 QInit(&CellLRU);
826 afs_cellindex = 0;
827 afs_cellalias_index = 0;
830 void
831 shutdown_cell()
833 struct afs_q *cq, *tq;
834 struct cell *tc;
836 RWLOCK_INIT(&afs_xcell, "afs_xcell");
838 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
839 tc = QTOC(cq);
840 tq = QNext(cq);
841 if (tc->cellName)
842 afs_osi_FreeStr(tc->cellName);
843 afs_osi_Free(tc, sizeof(struct cell));
845 QInit(&CellLRU);
848 struct cell_name *cn = afs_cellname_head;
850 while (cn) {
851 struct cell_name *next = cn->next;
853 afs_osi_FreeStr(cn->cellname);
854 afs_osi_Free(cn, sizeof(struct cell_name));
855 cn = next;
860 void
861 afs_RemoveCellEntry(struct server *srvp)
863 struct cell *tc;
864 afs_int32 j, k;
866 tc = srvp->cell;
867 if (!tc)
868 return;
870 /* Remove the server structure from the cell list - if there */
871 ObtainWriteLock(&tc->lock, 200);
872 for (j = k = 0; j < MAXCELLHOSTS; j++) {
873 if (!tc->cellHosts[j])
874 break;
875 if (tc->cellHosts[j] != srvp) {
876 tc->cellHosts[k++] = tc->cellHosts[j];
879 if (k == 0) {
880 /* What do we do if we remove the last one? */
882 for (; k < MAXCELLHOSTS; k++) {
883 tc->cellHosts[k] = 0;
885 ReleaseWriteLock(&tc->lock);
888 static int
889 afs_CellOrAliasExists_nl(char *aname)
891 struct cell *c;
892 struct cell_alias *ca;
894 c = afs_FindCellByName_nl(aname, READ_LOCK);
895 if (c) {
896 afs_PutCell(c, READ_LOCK);
897 return 1;
900 ca = afs_FindCellAlias(aname);
901 if (ca) {
902 afs_PutCellAlias(ca);
903 return 1;
906 return 0;
910 afs_CellOrAliasExists(char *aname)
912 int ret;
914 ObtainReadLock(&afs_xcell);
915 ret = afs_CellOrAliasExists_nl(aname);
916 ReleaseReadLock(&afs_xcell);
918 return ret;
922 afs_CellNumValid(afs_int32 cellnum)
924 struct cell_name *cn;
926 ObtainReadLock(&afs_xcell);
927 cn = afs_cellname_lookup_id(cellnum);
928 ReleaseReadLock(&afs_xcell);
929 if (cn) {
930 cn->used = 1;
931 return 1;
932 } else {
933 return 0;