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 "hcrypto/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
36 afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
37 afs_rwlock_t afsdb_req_lock; /* Serializes client requests */
38 static char afsdb_handler_running; /* Protected by GLOCK */
39 static char afsdb_handler_shutdown; /* Protected by GLOCK */
41 /* from cellconfig.h */
42 #define MAXCELLCHARS 64
44 /* lock moved to afsdb_req_lock for cmdebug */
51 * Terminate the AFSDB handler, used on shutdown.
56 if (afsdb_handler_running) {
57 afs_osi_Wakeup(&afsdb_req);
59 afsdb_handler_shutdown = 1;
60 afs_termState = AFSOP_STOP_RXEVENT;
61 afs_osi_Wakeup(&afs_termState);
66 * \brief Entry point for user-space AFSDB request handler.
67 * Reads cell data from kerlenMsg and add new cell, or alias.
68 * \param acellName Cell name. If a cell is found, it's name will be filled in here.
69 * \param acellNameLen Cell name length.
70 * \param kernelMsg Buffer containing data about host count, time out, and cell hosts ids.
71 * \return 0 for success, < 0 for error.
74 afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 * kernelMsg)
76 afs_int32 timeout, code;
77 afs_int32 cellHosts[AFS_MAXCELLHOSTS];
79 if (afsdb_handler_shutdown)
81 afsdb_handler_running = 1;
83 ObtainSharedLock(&afsdb_req_lock, 683);
84 if (afsdb_req.pending) {
87 UpgradeSToWLock(&afsdb_req_lock, 684);
88 hostCount = kernelMsg[0];
89 timeout = kernelMsg[1];
91 timeout += osi_Time();
93 for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
97 cellHosts[i] = kernelMsg[2 + i];
101 code = afs_NewCell(acellName, cellHosts, CNoSUID, NULL, 0, 0,
104 if (!hostCount || (code && code != EEXIST))
105 /* null out the cellname if the lookup failed */
106 afsdb_req.cellname = NULL;
108 /* If we found an alias, create it */
109 if (afs_strcasecmp(afsdb_req.cellname, acellName))
110 afs_NewCellAlias(afsdb_req.cellname, acellName);
112 /* Request completed, wake up the relevant thread */
113 afsdb_req.pending = 0;
114 afsdb_req.complete = 1;
115 afs_osi_Wakeup(&afsdb_req);
116 ConvertWToSLock(&afsdb_req_lock);
118 ConvertSToRLock(&afsdb_req_lock);
120 /* Wait for a request */
121 while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
122 ReleaseReadLock(&afsdb_req_lock);
123 afs_osi_Sleep(&afsdb_req);
124 ObtainReadLock(&afsdb_req_lock);
127 /* Check if we're shutting down */
128 if (afs_termState == AFSOP_STOP_AFSDB) {
129 ReleaseReadLock(&afsdb_req_lock);
131 /* Inform anyone waiting for us that we're going away */
132 afsdb_handler_shutdown = 1;
133 afsdb_handler_running = 0;
134 afs_osi_Wakeup(&afsdb_req);
136 afs_termState = AFSOP_STOP_RXEVENT;
137 afs_osi_Wakeup(&afs_termState);
141 /* Return the lookup request to userspace */
142 strncpy(acellName, afsdb_req.cellname, acellNameLen);
143 ReleaseReadLock(&afsdb_req_lock);
148 * \brief Query the AFSDB handler and wait for response.
150 * \return 0 for success. < 0 is error.
153 afs_GetCellHostsAFSDB(char *acellName)
156 if (!afsdb_handler_running)
159 ObtainWriteLock(&afsdb_client_lock, 685);
160 ObtainWriteLock(&afsdb_req_lock, 686);
162 afsdb_req.cellname = acellName;
164 afsdb_req.complete = 0;
165 afsdb_req.pending = 1;
166 afs_osi_Wakeup(&afsdb_req);
167 ConvertWToRLock(&afsdb_req_lock);
169 while (afsdb_handler_running && !afsdb_req.complete) {
170 ReleaseReadLock(&afsdb_req_lock);
171 afs_osi_Sleep(&afsdb_req);
172 ObtainReadLock(&afsdb_req_lock);
175 ReleaseReadLock(&afsdb_req_lock);
176 ReleaseWriteLock(&afsdb_client_lock);
178 if (afsdb_req.cellname) {
186 * Look up AFSDB for given cell name and create locally.
187 * \param acellName Cell name.
190 afs_LookupAFSDB(char *acellName)
193 char *cellName = afs_strdup(acellName);
195 code = afs_GetCellHostsAFSDB(cellName);
196 afs_Trace2(afs_iclSetp, CM_TRACE_AFSDB, ICL_TYPE_STRING, cellName,
197 ICL_TYPE_INT32, code);
198 afs_osi_FreeStr(cellName);
202 * Cell name-to-ID mapping
204 * afs_cellname_new: create a new cell name, optional cell number
205 * afs_cellname_lookup_id: look up a cell name
206 * afs_cellname_lookup_name: look up a cell number
207 * afs_cellname_ref: note that this cell name was referenced somewhere
208 * afs_cellname_init: load the list of cells from given inode
209 * afs_cellname_write: write in-kernel list of cells to disk
212 struct cell_name *afs_cellname_head; /* Export for kdump */
213 static afs_dcache_id_t afs_cellname_inode;
214 static int afs_cellname_inode_set;
215 static int afs_cellname_dirty;
216 static afs_int32 afs_cellnum_next;
219 * Create a new cell name, optional cell number.
220 * \param name Name of cell.
221 * \param cellnum Cellname number.
222 * \return Initialized structure.
224 static struct cell_name *
225 afs_cellname_new(char *name, afs_int32 cellnum)
227 struct cell_name *cn;
230 cellnum = afs_cellnum_next;
232 cn = afs_osi_Alloc(sizeof(*cn));
233 osi_Assert(cn != NULL);
234 cn->next = afs_cellname_head;
235 cn->cellnum = cellnum;
236 cn->cellname = afs_strdup(name);
238 afs_cellname_head = cn;
240 if (cellnum >= afs_cellnum_next)
241 afs_cellnum_next = cellnum + 1;
247 * Look up a cell name by id.
251 static struct cell_name *
252 afs_cellname_lookup_id(afs_int32 cellnum)
254 struct cell_name *cn;
256 for (cn = afs_cellname_head; cn; cn = cn->next)
257 if (cn->cellnum == cellnum)
264 * Look up a cell name.
265 * \param name Cell name.
268 static struct cell_name *
269 afs_cellname_lookup_name(char *name)
271 struct cell_name *cn;
273 for (cn = afs_cellname_head; cn; cn = cn->next)
274 if (strcmp(cn->cellname, name) == 0)
281 * Note that this cell name was referenced somewhere.
285 afs_cellname_ref(struct cell_name *cn)
289 afs_cellname_dirty = 1;
294 * \brief Load the list of cells from given inode.
295 * \param inode Source inode.
297 * \return 0 for success. < 0 for error.
300 afs_cellname_init(afs_dcache_id_t *inode, int lookupcode)
302 struct osi_file *tfile;
305 ObtainWriteLock(&afs_xcell, 692);
307 afs_cellnum_next = 1;
308 afs_cellname_dirty = 0;
310 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
311 ReleaseWriteLock(&afs_xcell);
315 ReleaseWriteLock(&afs_xcell);
319 tfile = osi_UFSOpen(inode);
321 ReleaseWriteLock(&afs_xcell);
325 afs_copy_inode(&afs_cellname_inode, inode);
326 afs_cellname_inode_set = 1;
329 afs_int32 cellnum, clen, magic;
332 cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
333 if (cc != sizeof(magic))
335 if (magic != AFS_CELLINFO_MAGIC)
339 cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
340 if (cc != sizeof(cellnum))
344 cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
345 if (cc != sizeof(clen))
349 cellname = afs_osi_Alloc(clen + 1);
353 cc = afs_osi_Read(tfile, off, cellname, clen);
355 afs_osi_Free(cellname, clen + 1);
359 cellname[clen] = '\0';
361 if (afs_cellname_lookup_name(cellname)
362 || afs_cellname_lookup_id(cellnum)) {
363 afs_osi_Free(cellname, clen + 1);
367 afs_cellname_new(cellname, cellnum);
368 afs_osi_Free(cellname, clen + 1);
372 ReleaseWriteLock(&afs_xcell);
377 * Write in-kernel list of cells to disk.
380 afs_cellname_write(void)
382 struct osi_file *tfile;
383 struct cell_name *cn;
386 if (!afs_cellname_dirty || !afs_cellname_inode_set)
388 if (afs_initState != 300)
391 ObtainWriteLock(&afs_xcell, 693);
392 afs_cellname_dirty = 0;
394 tfile = osi_UFSOpen(&afs_cellname_inode);
396 ReleaseWriteLock(&afs_xcell);
400 for (cn = afs_cellname_head; cn; cn = cn->next) {
401 afs_int32 magic, cellnum, clen;
407 magic = AFS_CELLINFO_MAGIC;
408 cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
409 if (cc != sizeof(magic))
413 cellnum = cn->cellnum;
414 cc = afs_osi_Write(tfile, off, &cellnum, sizeof(cellnum));
415 if (cc != sizeof(cellnum))
419 clen = strlen(cn->cellname);
420 cc = afs_osi_Write(tfile, off, &clen, sizeof(clen));
421 if (cc != sizeof(clen))
425 cc = afs_osi_Write(tfile, off, cn->cellname, clen);
432 ReleaseWriteLock(&afs_xcell);
437 * Cell alias implementation
439 * afs_FindCellAlias: look up cell alias by alias name
440 * afs_GetCellAlias: get cell alias by index (starting at 0)
441 * afs_PutCellAlias: put back a cell alias returned by Find or Get
442 * afs_NewCellAlias: create new cell alias entry
445 struct cell_alias *afs_cellalias_head; /* Export for kdump */
446 static afs_int32 afs_cellalias_index;
447 static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
450 * Look up cell alias by alias name.
452 * \return Found struct or NULL.
454 static struct cell_alias *
455 afs_FindCellAlias(char *alias)
457 struct cell_alias *tc;
459 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
460 if (!strcmp(alias, tc->alias))
466 * Get cell alias by index (starting at 0).
467 * \param index Cell index.
468 * \return Found struct or null.
471 afs_GetCellAlias(int index)
473 struct cell_alias *tc;
475 ObtainReadLock(&afs_xcell);
476 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
477 if (tc->index == index)
479 ReleaseReadLock(&afs_xcell);
486 * Put back a cell alias returned by Find or Get.
491 afs_PutCellAlias(struct cell_alias *a)
497 * Create new cell alias entry and update dynroot vnode.
503 afs_NewCellAlias(char *alias, char *cell)
505 struct cell_alias *tc;
507 ObtainSharedLock(&afs_xcell, 681);
508 if (afs_CellOrAliasExists_nl(alias)) {
509 ReleaseSharedLock(&afs_xcell);
513 UpgradeSToWLock(&afs_xcell, 682);
514 tc = afs_osi_Alloc(sizeof(struct cell_alias));
515 osi_Assert(tc != NULL);
516 tc->alias = afs_strdup(alias);
517 tc->cell = afs_strdup(cell);
518 tc->next = afs_cellalias_head;
519 tc->index = afs_cellalias_index++;
520 afs_cellalias_head = tc;
521 ReleaseWriteLock(&afs_xcell);
523 afs_DynrootInvalidate();
528 * Actual cell list implementation
530 * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
531 * afs_RefreshCell: look up cell information in AFSDB if timeout expired
533 * afs_TraverseCells: execute a callback for each existing cell
534 * afs_TraverseCells_nl: same as above except without locking afs_xcell
535 * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
537 * afs_FindCellByName: return a cell with a given name, if it exists
538 * afs_FindCellByName_nl: same as above, without locking afs_xcell
539 * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
540 * afs_GetCell: return a cell with a given cell number
541 * afs_GetCellStale: same as GetCell, but does not try to refresh the data
542 * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
544 * afs_GetPrimaryCell: return the primary cell, if any
545 * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
546 * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
547 * afs_SetPrimaryCell: set the primary cell name to the given cell name
549 * afs_NewCell: create or update a cell entry
552 struct afs_q CellLRU; /* Export for kdump */
553 static char *afs_thiscell = NULL;
554 afs_int32 afs_cellindex; /* Export for kdump */
557 * Bump given cell up to the front of the LRU queue.
558 * \param c Cell to set.
561 afs_UpdateCellLRU(struct cell *c)
563 ObtainWriteLock(&afs_xcell, 100);
565 QAdd(&CellLRU, &c->lruq);
566 ReleaseWriteLock(&afs_xcell);
570 * Look up cell information in AFSDB if timeout expired
571 * \param ac Cell to be refreshed.
575 afs_RefreshCell(struct cell *ac)
577 if (ac->states & CNoAFSDB)
579 if (!ac->cellHosts[0] || (ac->timeout && ac->timeout <= osi_Time()))
580 afs_LookupAFSDB(ac->cellName);
584 * Execute a callback for each existing cell, without a lock on afs_xcell.
585 * Iterate on CellLRU, and execute a callback for each cell until given arguments are met.
586 * \see afs_TraverseCells
587 * \param cb Traversal callback for each cell.
588 * \param arg Callback arguments.
589 * \return Found data or NULL.
592 afs_TraverseCells_nl(void *(*cb) (struct cell *, void *), void *arg)
594 struct afs_q *cq, *tq;
598 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
601 /* This is assuming that a NULL return is acceptable. */
617 * Execute a callback for each existing cell, with a lock on afs_xcell.
618 * \see afs_TraverseCells_nl
619 * \param cb Traversal callback for each cell.
621 * \return Found data or NULL.
624 afs_TraverseCells(void *(*cb) (struct cell *, void *), void *arg)
628 ObtainReadLock(&afs_xcell);
629 ret = afs_TraverseCells_nl(cb, arg);
630 ReleaseReadLock(&afs_xcell);
636 * Useful traversal callback: Match by name.
638 * \param arg Cell name (compared with cell->cellName).
639 * \return Returns found cell or NULL.
642 afs_choose_cell_by_name(struct cell *cell, void *arg)
648 return strcmp(cell->cellName, (char *)arg) ? NULL : cell;
653 * Useful traversal callback: Match by handle.
655 * \param arg Cell handle (compared with cell->cellHandle).
656 * \return Returns found cell or NULL.
659 afs_choose_cell_by_handle(struct cell *cell, void *arg)
665 return memcmp(cell->cellHandle, (char *)arg, 16) ? NULL : cell;
670 * Useful traversal callback: Match by cell number.
672 * \param arg Cell number (compared with cell->cellNum).
673 * \return Returns found cell or NULL.
676 afs_choose_cell_by_num(struct cell *cell, void *arg)
678 return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
682 * Useful traversal callback: Match by index.
684 * \param arg Cell index (compared with cell->cellIndex).
685 * \return Returns found cell or NULL.
688 afs_choose_cell_by_index(struct cell *cell, void *arg)
690 return (cell->cellIndex == *((afs_int32 *) arg)) ? cell : NULL;
694 * Return a cell with a given name, if it exists. No lock version.
695 * Does not check AFSDB.
696 * \param acellName Cell name.
697 * \param locktype Type of lock to be used (not used).
701 afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
703 return afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
707 * Return a cell with a given name, if it exists.It uses locks.
708 * Does not check AFSDB.
709 * \param acellName Cell name.
710 * \param locktype Type of lock to be used.
714 afs_FindCellByName(char *acellName, afs_int32 locktype)
716 return afs_TraverseCells(&afs_choose_cell_by_name, acellName);
720 * Same as FindCellByName but tries AFSDB if not found.
721 * \param acellName Cell name.
722 * \param locktype Type of lock to be used.
726 afs_GetCellByName(char *acellName, afs_int32 locktype)
730 tc = afs_FindCellByName(acellName, locktype);
732 afs_LookupAFSDB(acellName);
733 tc = afs_FindCellByName(acellName, locktype);
736 afs_cellname_ref(tc->cnamep);
737 afs_UpdateCellLRU(tc);
745 * Return a cell with a given cell number.
746 * \param cellnum Cell number.
747 * \param locktype Lock to be used.
751 afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
754 struct cell_name *cn;
756 tc = afs_GetCellStale(cellnum, locktype);
760 ObtainReadLock(&afs_xcell);
761 cn = afs_cellname_lookup_id(cellnum);
762 ReleaseReadLock(&afs_xcell);
764 tc = afs_GetCellByName(cn->cellname, locktype);
770 * Same as GetCell, but does not try to refresh the data.
771 * \param cellnum Cell number.
772 * \param locktype What lock should be used.
776 afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
780 tc = afs_TraverseCells(&afs_choose_cell_by_num, &cellnum);
782 afs_cellname_ref(tc->cnamep);
783 afs_UpdateCellLRU(tc);
789 * Return a cell with a given index number (starting at 0). Update CellLRU as well.
791 * \param locktype Type of lock used.
795 afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
799 tc = afs_TraverseCells(&afs_choose_cell_by_index, &index);
801 afs_UpdateCellLRU(tc);
806 * Return a cell with a given handle..
808 * \param locktype Type of lock used.
812 afs_GetCellByHandle(void *handle, afs_int32 locktype)
816 tc = afs_TraverseCells(&afs_choose_cell_by_handle, handle);
818 afs_UpdateCellLRU(tc);
823 * Return primary cell, if any.
824 * \param locktype Type of lock used.
828 afs_GetPrimaryCell(afs_int32 locktype)
830 return afs_GetCellByName(afs_thiscell, locktype);
834 * Return number of the primary cell.
836 * Cell number, or 0 if primary cell not found
839 afs_GetPrimaryCellNum(void)
842 afs_int32 cellNum = 0;
843 cell = afs_GetPrimaryCell(READ_LOCK);
845 cellNum = cell->cellNum;
846 afs_PutCell(cell, READ_LOCK);
852 * Returns true if the given cell is the primary cell.
857 afs_IsPrimaryCell(struct cell *cell)
859 /* Simple safe checking */
862 } else if (!afs_thiscell) {
863 /* This is simply a safety net to avoid seg faults especially when
864 * using a user-space library. afs_SetPrimaryCell() should be set
865 * prior to this call. */
866 afs_SetPrimaryCell(cell->cellName);
869 return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
874 * Returns afs_IsPrimaryCell(afs_GetCell(cellnum)).
879 afs_IsPrimaryCellNum(afs_int32 cellnum)
884 tc = afs_GetCellStale(cellnum, READ_LOCK);
886 primary = afs_IsPrimaryCell(tc);
887 afs_PutCell(tc, READ_LOCK);
894 * Set the primary cell name to the given cell name.
895 * \param acellName Cell name.
896 * \return 0 for success, < 0 for error.
899 afs_SetPrimaryCell(char *acellName)
901 ObtainWriteLock(&afs_xcell, 691);
903 afs_osi_FreeStr(afs_thiscell);
904 afs_thiscell = afs_strdup(acellName);
905 ReleaseWriteLock(&afs_xcell);
910 * Create or update a cell entry.
911 * \param acellName Name of cell.
912 * \param acellHosts Array of hosts that this cell has.
913 * \param aflags Cell flags.
915 * \param fsport File server port.
916 * \param vlport Volume server port.
917 * \param timeout Cell timeout value, 0 means static AFSDB entry.
921 afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
922 char *linkedcname, u_short fsport, u_short vlport, int timeout)
924 struct cell *tc, *tcl = 0;
925 afs_int32 i, newc = 0, code = 0;
928 AFS_STATCNT(afs_NewCell);
930 ObtainWriteLock(&afs_xcell, 103);
932 tc = afs_FindCellByName_nl(acellName, READ_LOCK);
936 tc = afs_osi_Alloc(sizeof(struct cell));
937 osi_Assert(tc != NULL);
938 memset(tc, 0, sizeof(*tc));
939 tc->cellName = afs_strdup(acellName);
940 tc->fsport = AFS_FSPORT;
941 tc->vlport = AFS_VLPORT;
943 MD5_Update(&m, tc->cellName, strlen(tc->cellName));
944 MD5_Final(tc->cellHandle, &m);
945 AFS_RWLOCK_INIT(&tc->lock, "cell lock");
949 ObtainWriteLock(&tc->lock, 688);
951 /* If the cell we've found has the correct name but no timeout,
952 * and we're called with a non-zero timeout, bail out: never
953 * override static configuration entries with AFSDB ones.
954 * One exception: if the original cell entry had no servers,
955 * it must get servers from AFSDB.
957 if (timeout && !tc->timeout && tc->cellHosts[0]) {
958 code = EEXIST; /* This code is checked for in afs_LookupAFSDB */
962 /* we don't want to keep pinging old vlservers which were down,
963 * since they don't matter any more. It's easier to do this than
964 * to remove the server from its various hash tables. */
965 for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
966 if (!tc->cellHosts[i])
968 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
969 tc->cellHosts[i]->flags |= SRVR_ISGONE;
977 if (aflags & CLinkedCell) {
982 tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
987 if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
988 tcl->lcellp->lcellp = (struct cell *)0;
989 tcl->lcellp->states &= ~CLinkedCell;
994 tc->states |= aflags;
995 tc->timeout = timeout;
997 memset(tc->cellHosts, 0, sizeof(tc->cellHosts));
998 for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
999 /* Get server for each host and link this cell in.*/
1001 afs_uint32 temp = acellHosts[i];
1004 ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0, NULL);
1006 ts->flags &= ~SRVR_ISGONE;
1007 /* Set the server as a host of the new cell. */
1008 tc->cellHosts[i] = ts;
1009 afs_PutServer(ts, WRITE_LOCK);
1011 afs_SortServers(tc->cellHosts, AFS_MAXCELLHOSTS); /* randomize servers */
1013 /* New cell: Build and add to LRU cell queue. */
1015 struct cell_name *cn;
1017 cn = afs_cellname_lookup_name(acellName);
1019 cn = afs_cellname_new(acellName, 0);
1022 tc->cellNum = cn->cellnum;
1023 tc->cellIndex = afs_cellindex++;
1024 afs_stats_cmperf.numCellsVisible++;
1025 QAdd(&CellLRU, &tc->lruq);
1028 ReleaseWriteLock(&tc->lock);
1029 ReleaseWriteLock(&afs_xcell);
1031 if (!(aflags & CHush))
1032 afs_DynrootInvalidate();
1037 afs_osi_FreeStr(tc->cellName);
1038 afs_osi_Free(tc, sizeof(struct cell));
1040 ReleaseWriteLock(&tc->lock);
1041 ReleaseWriteLock(&afs_xcell);
1046 * Miscellaneous stuff
1048 * afs_CellInit: perform whatever initialization is necessary
1049 * shutdown_cell: called on shutdown, should deallocate memory, etc
1050 * afs_RemoveCellEntry: remove a server from a cell's server list
1051 * afs_CellOrAliasExists: check if the given name exists as a cell or alias
1052 * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
1053 * afs_CellNumValid: check if a cell number is valid (also set the used flag)
1057 * Perform whatever initialization is necessary.
1062 static char CellInit_done = 0;
1069 AFS_RWLOCK_INIT(&afs_xcell, "afs_xcell");
1070 AFS_RWLOCK_INIT(&afsdb_client_lock, "afsdb_client_lock");
1071 AFS_RWLOCK_INIT(&afsdb_req_lock, "afsdb_req_lock");
1075 afs_cellalias_index = 0;
1079 * Called on shutdown, should deallocate memory, etc.
1084 struct afs_q *cq, *tq;
1087 #ifdef AFS_CACHE_VNODE_PATH
1088 if (cacheDiskType != AFS_FCACHE_TYPE_MEM) {
1089 afs_osi_FreeStr(afs_cellname_inode.ufs);
1092 AFS_RWLOCK_INIT(&afs_xcell, "afs_xcell");
1094 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1098 afs_osi_FreeStr(tc->cellName);
1099 afs_osi_Free(tc, sizeof(struct cell));
1104 struct cell_name *cn = afs_cellname_head;
1107 struct cell_name *next = cn->next;
1109 afs_osi_FreeStr(cn->cellname);
1110 afs_osi_Free(cn, sizeof(struct cell_name));
1117 * Remove a server from a cell's server list.
1118 * \param srvp Server to be removed.
1122 afs_RemoveCellEntry(struct server *srvp)
1131 /* Remove the server structure from the cell list - if there */
1132 ObtainWriteLock(&tc->lock, 200);
1133 for (j = k = 0; j < AFS_MAXCELLHOSTS; j++) {
1134 if (!tc->cellHosts[j])
1136 if (tc->cellHosts[j] != srvp) {
1137 tc->cellHosts[k++] = tc->cellHosts[j];
1141 /* What do we do if we remove the last one? */
1143 for (; k < AFS_MAXCELLHOSTS; k++) {
1144 tc->cellHosts[k] = 0;
1146 ReleaseWriteLock(&tc->lock);
1150 * Check if the given name exists as a cell or alias. Does not lock afs_xcell.
1155 afs_CellOrAliasExists_nl(char *aname)
1158 struct cell_alias *ca;
1160 c = afs_FindCellByName_nl(aname, READ_LOCK);
1162 afs_PutCell(c, READ_LOCK);
1166 ca = afs_FindCellAlias(aname);
1168 afs_PutCellAlias(ca);
1176 * Check if the given name exists as a cell or alias. Locks afs_xcell.
1181 afs_CellOrAliasExists(char *aname)
1185 ObtainReadLock(&afs_xcell);
1186 ret = afs_CellOrAliasExists_nl(aname);
1187 ReleaseReadLock(&afs_xcell);
1193 * Check if a cell number is valid (also set the used flag).
1195 * \return 1 - true, 0 - false
1198 afs_CellNumValid(afs_int32 cellnum)
1200 struct cell_name *cn;
1202 ObtainReadLock(&afs_xcell);
1203 cn = afs_cellname_lookup_id(cellnum);
1204 ReleaseReadLock(&afs_xcell);