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/sysincludes.h" /* Standard vendor system headers */
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h" /* afs statistics */
21 #include "afs/afs_osi.h"
22 #include "afs/afs_md5.h"
24 /* Local variables. */
25 afs_rwlock_t afs_xcell; /* Export for cmdebug peeking at locks */
28 * AFSDB implementation:
30 * afs_StopAFSDB: terminate the AFSDB handler, used on shutdown
31 * afs_AFSDBHandler: entry point for user-space AFSDB request handler
32 * afs_GetCellHostsAFSDB: query the AFSDB handler and wait for response
33 * afs_LookupAFSDB: look up AFSDB for given cell name and create locally
37 afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
38 afs_rwlock_t afsdb_req_lock; /* Serializes client requests */
39 static char afsdb_handler_running; /* Protected by GLOCK */
40 static char afsdb_handler_shutdown; /* Protected by GLOCK */
42 /* from cellconfig.h */
43 #define MAXCELLCHARS 64
45 /* lock moved to afsdb_req_lock for cmdebug */
52 * Terminate the AFSDB handler, used on shutdown.
57 if (afsdb_handler_running) {
58 afs_osi_Wakeup(&afsdb_req);
60 afsdb_handler_shutdown = 1;
61 afs_termState = AFSOP_STOP_RXEVENT;
62 afs_osi_Wakeup(&afs_termState);
67 * \brief Entry point for user-space AFSDB request handler.
68 * Reads cell data from kerlenMsg and add new cell, or alias.
69 * \param acellName Cell name. If a cell is found, it's name will be filled in here.
70 * \param acellNameLen Cell name length.
71 * \param kernelMsg Buffer containing data about host count, time out, and cell hosts ids.
72 * \return 0 for success, < 0 for error.
75 afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 * kernelMsg)
77 afs_int32 timeout, code;
78 afs_int32 cellHosts[AFS_MAXCELLHOSTS];
80 if (afsdb_handler_shutdown)
82 afsdb_handler_running = 1;
84 ObtainSharedLock(&afsdb_req_lock, 683);
85 if (afsdb_req.pending) {
88 UpgradeSToWLock(&afsdb_req_lock, 684);
89 hostCount = kernelMsg[0];
90 timeout = kernelMsg[1];
92 timeout += osi_Time();
94 for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
98 cellHosts[i] = kernelMsg[2 + i];
102 code = afs_NewCell(acellName, cellHosts, CNoSUID, NULL, 0, 0,
105 if (!hostCount || (code && code != EEXIST))
106 /* null out the cellname if the lookup failed */
107 afsdb_req.cellname = NULL;
109 /* If we found an alias, create it */
110 if (afs_strcasecmp(afsdb_req.cellname, acellName))
111 afs_NewCellAlias(afsdb_req.cellname, acellName);
113 /* Request completed, wake up the relevant thread */
114 afsdb_req.pending = 0;
115 afsdb_req.complete = 1;
116 afs_osi_Wakeup(&afsdb_req);
117 ConvertWToSLock(&afsdb_req_lock);
119 ConvertSToRLock(&afsdb_req_lock);
121 /* Wait for a request */
122 while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
123 ReleaseReadLock(&afsdb_req_lock);
124 afs_osi_Sleep(&afsdb_req);
125 ObtainReadLock(&afsdb_req_lock);
128 /* Check if we're shutting down */
129 if (afs_termState == AFSOP_STOP_AFSDB) {
130 ReleaseReadLock(&afsdb_req_lock);
132 /* Inform anyone waiting for us that we're going away */
133 afsdb_handler_shutdown = 1;
134 afsdb_handler_running = 0;
135 afs_osi_Wakeup(&afsdb_req);
137 afs_termState = AFSOP_STOP_RXEVENT;
138 afs_osi_Wakeup(&afs_termState);
142 /* Return the lookup request to userspace */
143 strncpy(acellName, afsdb_req.cellname, acellNameLen);
144 ReleaseReadLock(&afsdb_req_lock);
149 * \brief Query the AFSDB handler and wait for response.
151 * \return 0 for success. < 0 is error.
154 afs_GetCellHostsAFSDB(char *acellName)
157 if (!afsdb_handler_running)
160 ObtainWriteLock(&afsdb_client_lock, 685);
161 ObtainWriteLock(&afsdb_req_lock, 686);
163 afsdb_req.cellname = acellName;
165 afsdb_req.complete = 0;
166 afsdb_req.pending = 1;
167 afs_osi_Wakeup(&afsdb_req);
168 ConvertWToRLock(&afsdb_req_lock);
170 while (afsdb_handler_running && !afsdb_req.complete) {
171 ReleaseReadLock(&afsdb_req_lock);
172 afs_osi_Sleep(&afsdb_req);
173 ObtainReadLock(&afsdb_req_lock);
176 ReleaseReadLock(&afsdb_req_lock);
177 ReleaseWriteLock(&afsdb_client_lock);
179 if (afsdb_req.cellname) {
188 * Look up AFSDB for given cell name and create locally.
189 * \param acellName Cell name.
192 afs_LookupAFSDB(char *acellName)
196 char *cellName = afs_strdup(acellName);
198 code = afs_GetCellHostsAFSDB(cellName);
199 afs_Trace2(afs_iclSetp, CM_TRACE_AFSDB, ICL_TYPE_STRING, cellName,
200 ICL_TYPE_INT32, code);
201 afs_osi_FreeStr(cellName);
206 * Cell name-to-ID mapping
208 * afs_cellname_new: create a new cell name, optional cell number
209 * afs_cellname_lookup_id: look up a cell name
210 * afs_cellname_lookup_name: look up a cell number
211 * afs_cellname_ref: note that this cell name was referenced somewhere
212 * afs_cellname_init: load the list of cells from given inode
213 * afs_cellname_write: write in-kernel list of cells to disk
216 struct cell_name *afs_cellname_head; /* Export for kdump */
217 static afs_dcache_id_t afs_cellname_inode;
218 static int afs_cellname_inode_set;
219 static int afs_cellname_dirty;
220 static afs_int32 afs_cellnum_next;
223 * Create a new cell name, optional cell number.
224 * \param name Name of cell.
225 * \param cellnum Cellname number.
226 * \return Initialized structure.
228 static struct cell_name *
229 afs_cellname_new(char *name, afs_int32 cellnum)
231 struct cell_name *cn;
234 cellnum = afs_cellnum_next;
236 cn = (struct cell_name *)afs_osi_Alloc(sizeof(*cn));
237 cn->next = afs_cellname_head;
238 cn->cellnum = cellnum;
239 cn->cellname = afs_strdup(name);
241 afs_cellname_head = cn;
243 if (cellnum >= afs_cellnum_next)
244 afs_cellnum_next = cellnum + 1;
250 * Look up a cell name by id.
254 static struct cell_name *
255 afs_cellname_lookup_id(afs_int32 cellnum)
257 struct cell_name *cn;
259 for (cn = afs_cellname_head; cn; cn = cn->next)
260 if (cn->cellnum == cellnum)
267 * Look up a cell name.
268 * \param name Cell name.
271 static struct cell_name *
272 afs_cellname_lookup_name(char *name)
274 struct cell_name *cn;
276 for (cn = afs_cellname_head; cn; cn = cn->next)
277 if (strcmp(cn->cellname, name) == 0)
284 * Note that this cell name was referenced somewhere.
288 afs_cellname_ref(struct cell_name *cn)
292 afs_cellname_dirty = 1;
297 * \brief Load the list of cells from given inode.
298 * \param inode Source inode.
300 * \return 0 for success. < 0 for error.
303 afs_cellname_init(afs_dcache_id_t *inode, int lookupcode)
305 struct osi_file *tfile;
308 ObtainWriteLock(&afs_xcell, 692);
310 afs_cellnum_next = 1;
311 afs_cellname_dirty = 0;
313 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
314 ReleaseWriteLock(&afs_xcell);
318 ReleaseWriteLock(&afs_xcell);
322 tfile = osi_UFSOpen(inode);
324 ReleaseWriteLock(&afs_xcell);
328 afs_copy_inode(&afs_cellname_inode, inode);
329 afs_cellname_inode_set = 1;
332 afs_int32 cellnum, clen, magic;
333 struct cell_name *cn;
336 cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
337 if (cc != sizeof(magic))
339 if (magic != AFS_CELLINFO_MAGIC)
343 cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
344 if (cc != sizeof(cellnum))
348 cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
349 if (cc != sizeof(clen))
353 cellname = afs_osi_Alloc(clen + 1);
357 cc = afs_osi_Read(tfile, off, cellname, clen);
359 afs_osi_Free(cellname, clen + 1);
363 cellname[clen] = '\0';
365 if (afs_cellname_lookup_name(cellname)
366 || afs_cellname_lookup_id(cellnum)) {
367 afs_osi_Free(cellname, clen + 1);
371 cn = afs_cellname_new(cellname, cellnum);
372 afs_osi_Free(cellname, clen + 1);
376 ReleaseWriteLock(&afs_xcell);
381 * Write in-kernel list of cells to disk.
384 afs_cellname_write(void)
386 struct osi_file *tfile;
387 struct cell_name *cn;
390 if (!afs_cellname_dirty || !afs_cellname_inode_set)
392 if (afs_initState != 300)
395 ObtainWriteLock(&afs_xcell, 693);
396 afs_cellname_dirty = 0;
398 tfile = osi_UFSOpen(&afs_cellname_inode);
400 ReleaseWriteLock(&afs_xcell);
404 for (cn = afs_cellname_head; cn; cn = cn->next) {
405 afs_int32 magic, cellnum, clen;
411 magic = AFS_CELLINFO_MAGIC;
412 cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
413 if (cc != sizeof(magic))
417 cellnum = cn->cellnum;
418 cc = afs_osi_Write(tfile, off, &cellnum, sizeof(cellnum));
419 if (cc != sizeof(cellnum))
423 clen = strlen(cn->cellname);
424 cc = afs_osi_Write(tfile, off, &clen, sizeof(clen));
425 if (cc != sizeof(clen))
429 cc = afs_osi_Write(tfile, off, cn->cellname, clen);
436 ReleaseWriteLock(&afs_xcell);
441 * Cell alias implementation
443 * afs_FindCellAlias: look up cell alias by alias name
444 * afs_GetCellAlias: get cell alias by index (starting at 0)
445 * afs_PutCellAlias: put back a cell alias returned by Find or Get
446 * afs_NewCellAlias: create new cell alias entry
449 struct cell_alias *afs_cellalias_head; /* Export for kdump */
450 static afs_int32 afs_cellalias_index;
451 static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
454 * Look up cell alias by alias name.
456 * \return Found struct or NULL.
458 static struct cell_alias *
459 afs_FindCellAlias(char *alias)
461 struct cell_alias *tc;
463 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
464 if (!strcmp(alias, tc->alias))
470 * Get cell alias by index (starting at 0).
471 * \param index Cell index.
472 * \return Found struct or null.
475 afs_GetCellAlias(int index)
477 struct cell_alias *tc;
479 ObtainReadLock(&afs_xcell);
480 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
481 if (tc->index == index)
483 ReleaseReadLock(&afs_xcell);
490 * Put back a cell alias returned by Find or Get.
495 afs_PutCellAlias(struct cell_alias *a)
501 * Create new cell alias entry and update dynroot vnode.
507 afs_NewCellAlias(char *alias, char *cell)
509 struct cell_alias *tc;
511 ObtainSharedLock(&afs_xcell, 681);
512 if (afs_CellOrAliasExists_nl(alias)) {
513 ReleaseSharedLock(&afs_xcell);
517 UpgradeSToWLock(&afs_xcell, 682);
518 tc = (struct cell_alias *)afs_osi_Alloc(sizeof(struct cell_alias));
519 tc->alias = afs_strdup(alias);
520 tc->cell = afs_strdup(cell);
521 tc->next = afs_cellalias_head;
522 tc->index = afs_cellalias_index++;
523 afs_cellalias_head = tc;
524 ReleaseWriteLock(&afs_xcell);
526 afs_DynrootInvalidate();
531 * Actual cell list implementation
533 * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
534 * afs_RefreshCell: look up cell information in AFSDB if timeout expired
536 * afs_TraverseCells: execute a callback for each existing cell
537 * afs_TraverseCells_nl: same as above except without locking afs_xcell
538 * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
540 * afs_FindCellByName: return a cell with a given name, if it exists
541 * afs_FindCellByName_nl: same as above, without locking afs_xcell
542 * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
543 * afs_GetCell: return a cell with a given cell number
544 * afs_GetCellStale: same as GetCell, but does not try to refresh the data
545 * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
547 * afs_GetPrimaryCell: return the primary cell, if any
548 * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
549 * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
550 * afs_SetPrimaryCell: set the primary cell name to the given cell name
552 * afs_NewCell: create or update a cell entry
555 struct afs_q CellLRU; /* Export for kdump */
556 static char *afs_thiscell;
557 afs_int32 afs_cellindex; /* Export for kdump */
560 * Bump given cell up to the front of the LRU queue.
561 * \param c Cell to set.
564 afs_UpdateCellLRU(struct cell *c)
566 ObtainWriteLock(&afs_xcell, 100);
568 QAdd(&CellLRU, &c->lruq);
569 ReleaseWriteLock(&afs_xcell);
573 * Look up cell information in AFSDB if timeout expired
574 * \param ac Cell to be refreshed.
578 afs_RefreshCell(struct cell *ac)
580 if (ac->states & CNoAFSDB)
582 if (!ac->cellHosts[0] || (ac->timeout && ac->timeout <= osi_Time()))
583 afs_LookupAFSDB(ac->cellName);
587 * Execute a callback for each existing cell, without a lock on afs_xcell.
588 * Iterate on CellLRU, and execute a callback for each cell until given arguments are met.
589 * \see afs_TraverseCells
590 * \param cb Traversal callback for each cell.
591 * \param arg Callback arguments.
592 * \return Found data or NULL.
595 afs_TraverseCells_nl(void *(*cb) (struct cell *, void *), void *arg)
597 struct afs_q *cq, *tq;
601 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
604 /* This is assuming that a NULL return is acceptable. */
620 * Execute a callback for each existing cell, with a lock on afs_xcell.
621 * \see afs_TraverseCells_nl
622 * \param cb Traversal callback for each cell.
624 * \return Found data or NULL.
627 afs_TraverseCells(void *(*cb) (struct cell *, void *), void *arg)
631 ObtainReadLock(&afs_xcell);
632 ret = afs_TraverseCells_nl(cb, arg);
633 ReleaseReadLock(&afs_xcell);
639 * Useful traversal callback: Match by name.
641 * \param arg Cell name (compared with cell->cellName).
642 * \return Returns found cell or NULL.
645 afs_choose_cell_by_name(struct cell *cell, void *arg)
651 return strcmp(cell->cellName, (char *)arg) ? NULL : cell;
656 * Useful traversal callback: Match by handle.
658 * \param arg Cell handle (compared with cell->cellHandle).
659 * \return Returns found cell or NULL.
662 afs_choose_cell_by_handle(struct cell *cell, void *arg)
668 return memcmp(cell->cellHandle, (char *)arg, 16) ? NULL : cell;
673 * Useful traversal callback: Match by cell number.
675 * \param arg Cell number (compared with cell->cellNum).
676 * \return Returns found cell or NULL.
679 afs_choose_cell_by_num(struct cell *cell, void *arg)
681 return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
685 * Useful traversal callback: Match by index.
687 * \param arg Cell index (compared with cell->cellIndex).
688 * \return Returns found cell or NULL.
691 afs_choose_cell_by_index(struct cell *cell, void *arg)
693 return (cell->cellIndex == *((afs_int32 *) arg)) ? cell : NULL;
697 * Return a cell with a given name, if it exists. No lock version.
698 * Does not check AFSDB.
699 * \param acellName Cell name.
700 * \param locktype Type of lock to be used (not used).
704 afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
706 return afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
710 * Return a cell with a given name, if it exists.It uses locks.
711 * Does not check AFSDB.
712 * \param acellName Cell name.
713 * \param locktype Type of lock to be used.
717 afs_FindCellByName(char *acellName, afs_int32 locktype)
719 return afs_TraverseCells(&afs_choose_cell_by_name, acellName);
723 * Same as FindCellByName but tries AFSDB if not found.
724 * \param acellName Cell name.
725 * \param locktype Type of lock to be used.
729 afs_GetCellByName(char *acellName, afs_int32 locktype)
733 tc = afs_FindCellByName(acellName, locktype);
735 afs_LookupAFSDB(acellName);
736 tc = afs_FindCellByName(acellName, locktype);
739 afs_cellname_ref(tc->cnamep);
740 afs_UpdateCellLRU(tc);
748 * Return a cell with a given cell number.
749 * \param cellnum Cell number.
750 * \param locktype Lock to be used.
754 afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
757 struct cell_name *cn;
759 tc = afs_GetCellStale(cellnum, locktype);
763 ObtainReadLock(&afs_xcell);
764 cn = afs_cellname_lookup_id(cellnum);
765 ReleaseReadLock(&afs_xcell);
767 tc = afs_GetCellByName(cn->cellname, locktype);
773 * Same as GetCell, but does not try to refresh the data.
774 * \param cellnum Cell number.
775 * \param locktype What lock should be used.
779 afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
783 tc = afs_TraverseCells(&afs_choose_cell_by_num, &cellnum);
785 afs_cellname_ref(tc->cnamep);
786 afs_UpdateCellLRU(tc);
792 * Return a cell with a given index number (starting at 0). Update CellLRU as well.
794 * \param locktype Type of lock used.
798 afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
802 tc = afs_TraverseCells(&afs_choose_cell_by_index, &index);
804 afs_UpdateCellLRU(tc);
809 * Return a cell with a given handle..
811 * \param locktype Type of lock used.
815 afs_GetCellByHandle(void *handle, afs_int32 locktype)
819 tc = afs_TraverseCells(&afs_choose_cell_by_handle, handle);
821 afs_UpdateCellLRU(tc);
826 * Return primary cell, if any.
827 * \param locktype Type of lock used.
831 afs_GetPrimaryCell(afs_int32 locktype)
833 return afs_GetCellByName(afs_thiscell, locktype);
837 * Returns true if the given cell is the primary cell.
842 afs_IsPrimaryCell(struct cell *cell)
844 /* Simple safe checking */
847 } else if (!afs_thiscell) {
848 /* This is simply a safety net to avoid seg faults especially when
849 * using a user-space library. afs_SetPrimaryCell() should be set
850 * prior to this call. */
851 afs_SetPrimaryCell(cell->cellName);
854 return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
859 * Returns afs_IsPrimaryCell(afs_GetCell(cellnum)).
864 afs_IsPrimaryCellNum(afs_int32 cellnum)
869 tc = afs_GetCellStale(cellnum, READ_LOCK);
871 primary = afs_IsPrimaryCell(tc);
872 afs_PutCell(tc, READ_LOCK);
879 * Set the primary cell name to the given cell name.
880 * \param acellName Cell name.
881 * \return 0 for success, < 0 for error.
884 afs_SetPrimaryCell(char *acellName)
886 ObtainWriteLock(&afs_xcell, 691);
888 afs_osi_FreeStr(afs_thiscell);
889 afs_thiscell = afs_strdup(acellName);
890 ReleaseWriteLock(&afs_xcell);
895 * Create or update a cell entry.
896 * \param acellName Name of cell.
897 * \param acellHosts Array of hosts that this cell has.
898 * \param aflags Cell flags.
900 * \param fsport File server port.
901 * \param vlport Volume server port.
902 * \param timeout Cell timeout value, 0 means static AFSDB entry.
906 afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
907 char *linkedcname, u_short fsport, u_short vlport, int timeout)
909 struct cell *tc, *tcl = 0;
910 afs_int32 i, newc = 0, code = 0;
912 AFS_STATCNT(afs_NewCell);
914 ObtainWriteLock(&afs_xcell, 103);
916 tc = afs_FindCellByName_nl(acellName, READ_LOCK);
920 tc = (struct cell *)afs_osi_Alloc(sizeof(struct cell));
921 memset(tc, 0, sizeof(*tc));
922 tc->cellName = afs_strdup(acellName);
923 tc->fsport = AFS_FSPORT;
924 tc->vlport = AFS_VLPORT;
925 AFS_MD5_String(tc->cellHandle, tc->cellName, strlen(tc->cellName));
926 AFS_RWLOCK_INIT(&tc->lock, "cell lock");
930 ObtainWriteLock(&tc->lock, 688);
932 /* If the cell we've found has the correct name but no timeout,
933 * and we're called with a non-zero timeout, bail out: never
934 * override static configuration entries with AFSDB ones.
935 * One exception: if the original cell entry had no servers,
936 * it must get servers from AFSDB.
938 if (timeout && !tc->timeout && tc->cellHosts[0]) {
939 code = EEXIST; /* This code is checked for in afs_LookupAFSDB */
943 /* we don't want to keep pinging old vlservers which were down,
944 * since they don't matter any more. It's easier to do this than
945 * to remove the server from its various hash tables. */
946 for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
947 if (!tc->cellHosts[i])
949 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
950 tc->cellHosts[i]->flags |= SRVR_ISGONE;
958 if (aflags & CLinkedCell) {
963 tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
968 if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
969 tcl->lcellp->lcellp = (struct cell *)0;
970 tcl->lcellp->states &= ~CLinkedCell;
975 tc->states |= aflags;
976 tc->timeout = timeout;
978 memset(tc->cellHosts, 0, sizeof(tc->cellHosts));
979 for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
980 /* Get server for each host and link this cell in.*/
982 afs_uint32 temp = acellHosts[i];
985 ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
987 ts->flags &= ~SRVR_ISGONE;
988 /* Set the server as a host of the new cell. */
989 tc->cellHosts[i] = ts;
990 afs_PutServer(ts, WRITE_LOCK);
992 afs_SortServers(tc->cellHosts, AFS_MAXCELLHOSTS); /* randomize servers */
994 /* New cell: Build and add to LRU cell queue. */
996 struct cell_name *cn;
998 cn = afs_cellname_lookup_name(acellName);
1000 cn = afs_cellname_new(acellName, 0);
1003 tc->cellNum = cn->cellnum;
1004 tc->cellIndex = afs_cellindex++;
1005 afs_stats_cmperf.numCellsVisible++;
1006 QAdd(&CellLRU, &tc->lruq);
1009 ReleaseWriteLock(&tc->lock);
1010 ReleaseWriteLock(&afs_xcell);
1012 afs_DynrootInvalidate();
1017 afs_osi_FreeStr(tc->cellName);
1018 afs_osi_Free(tc, sizeof(struct cell));
1020 ReleaseWriteLock(&tc->lock);
1021 ReleaseWriteLock(&afs_xcell);
1026 * Miscellaneous stuff
1028 * afs_CellInit: perform whatever initialization is necessary
1029 * shutdown_cell: called on shutdown, should deallocate memory, etc
1030 * afs_RemoveCellEntry: remove a server from a cell's server list
1031 * afs_CellOrAliasExists: check if the given name exists as a cell or alias
1032 * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
1033 * afs_CellNumValid: check if a cell number is valid (also set the used flag)
1037 * Perform whatever initialization is necessary.
1042 AFS_RWLOCK_INIT(&afs_xcell, "afs_xcell");
1043 #ifdef AFS_AFSDB_ENV
1044 AFS_RWLOCK_INIT(&afsdb_client_lock, "afsdb_client_lock");
1045 AFS_RWLOCK_INIT(&afsdb_req_lock, "afsdb_req_lock");
1050 afs_cellalias_index = 0;
1054 * Called on shutdown, should deallocate memory, etc.
1059 struct afs_q *cq, *tq;
1062 AFS_RWLOCK_INIT(&afs_xcell, "afs_xcell");
1064 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1068 afs_osi_FreeStr(tc->cellName);
1069 afs_osi_Free(tc, sizeof(struct cell));
1074 struct cell_name *cn = afs_cellname_head;
1077 struct cell_name *next = cn->next;
1079 afs_osi_FreeStr(cn->cellname);
1080 afs_osi_Free(cn, sizeof(struct cell_name));
1087 * Remove a server from a cell's server list.
1088 * \param srvp Server to be removed.
1092 afs_RemoveCellEntry(struct server *srvp)
1101 /* Remove the server structure from the cell list - if there */
1102 ObtainWriteLock(&tc->lock, 200);
1103 for (j = k = 0; j < AFS_MAXCELLHOSTS; j++) {
1104 if (!tc->cellHosts[j])
1106 if (tc->cellHosts[j] != srvp) {
1107 tc->cellHosts[k++] = tc->cellHosts[j];
1111 /* What do we do if we remove the last one? */
1113 for (; k < AFS_MAXCELLHOSTS; k++) {
1114 tc->cellHosts[k] = 0;
1116 ReleaseWriteLock(&tc->lock);
1120 * Check if the given name exists as a cell or alias. Does not lock afs_xcell.
1125 afs_CellOrAliasExists_nl(char *aname)
1128 struct cell_alias *ca;
1130 c = afs_FindCellByName_nl(aname, READ_LOCK);
1132 afs_PutCell(c, READ_LOCK);
1136 ca = afs_FindCellAlias(aname);
1138 afs_PutCellAlias(ca);
1146 * Check if the given name exists as a cell or alias. Locks afs_xcell.
1151 afs_CellOrAliasExists(char *aname)
1155 ObtainReadLock(&afs_xcell);
1156 ret = afs_CellOrAliasExists_nl(aname);
1157 ReleaseReadLock(&afs_xcell);
1163 * Check if a cell number is valid (also set the used flag).
1165 * \return 1 - true, 0 - false
1168 afs_CellNumValid(afs_int32 cellnum)
1170 struct cell_name *cn;
1172 ObtainReadLock(&afs_xcell);
1173 cn = afs_cellname_lookup_id(cellnum);
1174 ReleaseReadLock(&afs_xcell);