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"
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"
24 #include "afs/afs_md5.h"
26 /* Local variables. */
27 afs_rwlock_t afs_xcell; /* Export for cmdebug peeking at locks */
30 * AFSDB implementation:
32 * afs_StopAFSDB: terminate the AFSDB handler, used on shutdown
33 * afs_AFSDBHandler: entry point for user-space AFSDB request handler
34 * afs_GetCellHostsAFSDB: query the AFSDB handler and wait for response
35 * afs_LookupAFSDB: look up AFSDB for given cell name and create locally
39 afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
40 afs_rwlock_t afsdb_req_lock; /* Serializes client requests */
41 static char afsdb_handler_running; /* Protected by GLOCK */
42 static char afsdb_handler_shutdown; /* Protected by GLOCK */
44 /* from cellconfig.h */
45 #define MAXCELLCHARS 64
47 /* lock moved to afsdb_req_lock for cmdebug */
54 * Terminate the AFSDB handler, used on shutdown.
59 if (afsdb_handler_running) {
60 afs_osi_Wakeup(&afsdb_req);
62 afsdb_handler_shutdown = 1;
63 afs_termState = AFSOP_STOP_RXEVENT;
68 * \brief Entry point for user-space AFSDB request handler.
69 * Reads cell data from kerlenMsg and add new cell, or alias.
70 * \param acellName Cell name. If a cell is found, it's name will be filled in here.
71 * \param acellNameLen Cell name length.
72 * \param kernelMsg Buffer containing data about host count, time out, and cell hosts ids.
73 * \return 0 for success, < 0 for error.
76 afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 * kernelMsg)
78 afs_int32 timeout, code;
79 afs_int32 cellHosts[MAXCELLHOSTS];
81 if (afsdb_handler_shutdown)
83 afsdb_handler_running = 1;
85 ObtainSharedLock(&afsdb_req_lock, 683);
86 if (afsdb_req.pending) {
89 UpgradeSToWLock(&afsdb_req_lock, 684);
90 hostCount = kernelMsg[0];
91 timeout = kernelMsg[1];
93 timeout += osi_Time();
95 for (i = 0; i < MAXCELLHOSTS; i++) {
99 cellHosts[i] = kernelMsg[2 + i];
103 code = afs_NewCell(acellName, cellHosts, CNoSUID, NULL, 0, 0,
106 if (!hostCount || (code && code != EEXIST))
107 /* null out the cellname if the lookup failed */
108 afsdb_req.cellname = NULL;
110 /* If we found an alias, create it */
111 if (afs_strcasecmp(afsdb_req.cellname, acellName))
112 afs_NewCellAlias(afsdb_req.cellname, acellName);
114 /* Request completed, wake up the relevant thread */
115 afsdb_req.pending = 0;
116 afsdb_req.complete = 1;
117 afs_osi_Wakeup(&afsdb_req);
118 ConvertWToSLock(&afsdb_req_lock);
120 ConvertSToRLock(&afsdb_req_lock);
122 /* Wait for a request */
123 while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
124 ReleaseReadLock(&afsdb_req_lock);
125 afs_osi_Sleep(&afsdb_req);
126 ObtainReadLock(&afsdb_req_lock);
129 /* Check if we're shutting down */
130 if (afs_termState == AFSOP_STOP_AFSDB) {
131 ReleaseReadLock(&afsdb_req_lock);
133 /* Inform anyone waiting for us that we're going away */
134 afsdb_handler_shutdown = 1;
135 afsdb_handler_running = 0;
136 afs_osi_Wakeup(&afsdb_req);
138 afs_termState = AFSOP_STOP_RXEVENT;
139 afs_osi_Wakeup(&afs_termState);
143 /* Return the lookup request to userspace */
144 strncpy(acellName, afsdb_req.cellname, acellNameLen);
145 ReleaseReadLock(&afsdb_req_lock);
150 * \brief Query the AFSDB handler and wait for response.
152 * \return 0 for success. < 0 is error.
155 afs_GetCellHostsAFSDB(char *acellName)
158 if (!afsdb_handler_running)
161 ObtainWriteLock(&afsdb_client_lock, 685);
162 ObtainWriteLock(&afsdb_req_lock, 686);
164 afsdb_req.cellname = acellName;
166 afsdb_req.complete = 0;
167 afsdb_req.pending = 1;
168 afs_osi_Wakeup(&afsdb_req);
169 ConvertWToRLock(&afsdb_req_lock);
171 while (afsdb_handler_running && !afsdb_req.complete) {
172 ReleaseReadLock(&afsdb_req_lock);
173 afs_osi_Sleep(&afsdb_req);
174 ObtainReadLock(&afsdb_req_lock);
177 ReleaseReadLock(&afsdb_req_lock);
178 ReleaseWriteLock(&afsdb_client_lock);
180 if (afsdb_req.cellname) {
189 * Look up AFSDB for given cell name and create locally.
190 * \param acellName Cell name.
193 afs_LookupAFSDB(char *acellName)
197 char *cellName = afs_strdup(acellName);
199 code = afs_GetCellHostsAFSDB(cellName);
200 afs_Trace2(afs_iclSetp, CM_TRACE_AFSDB, ICL_TYPE_STRING, cellName,
201 ICL_TYPE_INT32, code);
202 afs_osi_FreeStr(cellName);
207 * Cell name-to-ID mapping
209 * afs_cellname_new: create a new cell name, optional cell number
210 * afs_cellname_lookup_id: look up a cell name
211 * afs_cellname_lookup_name: look up a cell number
212 * afs_cellname_ref: note that this cell name was referenced somewhere
213 * afs_cellname_init: load the list of cells from given inode
214 * afs_cellname_write: write in-kernel list of cells to disk
217 struct cell_name *afs_cellname_head; /* Export for kdump */
218 #if defined(LINUX_USE_FH)
219 struct fid afs_cellname_fh;
220 int afs_cellname_fh_type;
221 static int afs_cellname_fh_set;
223 static ino_t afs_cellname_inode;
224 static int afs_cellname_inode_set;
226 static int afs_cellname_dirty;
227 static afs_int32 afs_cellnum_next;
230 * Create a new cell name, optional cell number.
231 * \param name Name of cell.
232 * \param cellnum Cellname number.
233 * \return Initialized structure.
235 static struct cell_name *
236 afs_cellname_new(char *name, afs_int32 cellnum)
238 struct cell_name *cn;
241 cellnum = afs_cellnum_next;
243 cn = (struct cell_name *)afs_osi_Alloc(sizeof(*cn));
244 cn->next = afs_cellname_head;
245 cn->cellnum = cellnum;
246 cn->cellname = afs_strdup(name);
248 afs_cellname_head = cn;
250 if (cellnum >= afs_cellnum_next)
251 afs_cellnum_next = cellnum + 1;
257 * Look up a cell name by id.
261 static struct cell_name *
262 afs_cellname_lookup_id(afs_int32 cellnum)
264 struct cell_name *cn;
266 for (cn = afs_cellname_head; cn; cn = cn->next)
267 if (cn->cellnum == cellnum)
274 * Look up a cell name.
275 * \param name Cell name.
278 static struct cell_name *
279 afs_cellname_lookup_name(char *name)
281 struct cell_name *cn;
283 for (cn = afs_cellname_head; cn; cn = cn->next)
284 if (strcmp(cn->cellname, name) == 0)
291 * Note that this cell name was referenced somewhere.
295 afs_cellname_ref(struct cell_name *cn)
299 afs_cellname_dirty = 1;
304 * \brief Load the list of cells from given inode.
305 * \param inode Source inode.
307 * \return 0 for success. < 0 for error.
310 #if defined(LINUX_USE_FH)
311 afs_cellname_init(struct fid *fh, int fh_type, int lookupcode)
313 afs_cellname_init(ino_t inode, int lookupcode)
316 struct osi_file *tfile;
319 ObtainWriteLock(&afs_xcell, 692);
321 afs_cellnum_next = 1;
322 afs_cellname_dirty = 0;
324 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
325 ReleaseWriteLock(&afs_xcell);
329 ReleaseWriteLock(&afs_xcell);
333 #if defined(LINUX_USE_FH)
334 tfile = osi_UFSOpen_fh(fh, fh_type);
336 tfile = osi_UFSOpen(inode);
339 ReleaseWriteLock(&afs_xcell);
343 #if defined(LINUX_USE_FH)
344 memcpy(&afs_cellname_fh, fh, sizeof(struct fid));
345 afs_cellname_fh_type = fh_type;
346 afs_cellname_fh_set = 1;
348 afs_cellname_inode = inode;
349 afs_cellname_inode_set = 1;
353 afs_int32 cellnum, clen, magic;
354 struct cell_name *cn;
357 cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
358 if (cc != sizeof(magic))
360 if (magic != AFS_CELLINFO_MAGIC)
364 cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
365 if (cc != sizeof(cellnum))
369 cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
370 if (cc != sizeof(clen))
374 cellname = afs_osi_Alloc(clen + 1);
378 cc = afs_osi_Read(tfile, off, cellname, clen);
380 afs_osi_Free(cellname, clen + 1);
384 cellname[clen] = '\0';
386 if (afs_cellname_lookup_name(cellname)
387 || afs_cellname_lookup_id(cellnum)) {
388 afs_osi_Free(cellname, clen + 1);
392 cn = afs_cellname_new(cellname, cellnum);
393 afs_osi_Free(cellname, clen + 1);
397 ReleaseWriteLock(&afs_xcell);
402 * Write in-kernel list of cells to disk.
405 afs_cellname_write(void)
407 struct osi_file *tfile;
408 struct cell_name *cn;
411 #if defined(LINUX_USE_FH)
412 if (!afs_cellname_dirty || !afs_cellname_fh_set)
414 if (!afs_cellname_dirty || !afs_cellname_inode_set)
417 if (afs_initState != 300)
420 ObtainWriteLock(&afs_xcell, 693);
421 afs_cellname_dirty = 0;
423 #if defined(LINUX_USE_FH)
424 tfile = osi_UFSOpen_fh(&afs_cellname_fh, afs_cellname_fh_type);
426 tfile = osi_UFSOpen(afs_cellname_inode);
429 ReleaseWriteLock(&afs_xcell);
433 for (cn = afs_cellname_head; cn; cn = cn->next) {
434 afs_int32 magic, cellnum, clen;
440 magic = AFS_CELLINFO_MAGIC;
441 cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
442 if (cc != sizeof(magic))
446 cellnum = cn->cellnum;
447 cc = afs_osi_Write(tfile, off, &cellnum, sizeof(cellnum));
448 if (cc != sizeof(cellnum))
452 clen = strlen(cn->cellname);
453 cc = afs_osi_Write(tfile, off, &clen, sizeof(clen));
454 if (cc != sizeof(clen))
458 cc = afs_osi_Write(tfile, off, cn->cellname, clen);
465 ReleaseWriteLock(&afs_xcell);
470 * Cell alias implementation
472 * afs_FindCellAlias: look up cell alias by alias name
473 * afs_GetCellAlias: get cell alias by index (starting at 0)
474 * afs_PutCellAlias: put back a cell alias returned by Find or Get
475 * afs_NewCellAlias: create new cell alias entry
478 struct cell_alias *afs_cellalias_head; /* Export for kdump */
479 static afs_int32 afs_cellalias_index;
480 static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
483 * Look up cell alias by alias name.
485 * \return Found struct or NULL.
487 static struct cell_alias *
488 afs_FindCellAlias(char *alias)
490 struct cell_alias *tc;
492 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
493 if (!strcmp(alias, tc->alias))
499 * Get cell alias by index (starting at 0).
500 * \param index Cell index.
501 * \return Found struct or null.
504 afs_GetCellAlias(int index)
506 struct cell_alias *tc;
508 ObtainReadLock(&afs_xcell);
509 for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
510 if (tc->index == index)
512 ReleaseReadLock(&afs_xcell);
519 * Put back a cell alias returned by Find or Get.
524 afs_PutCellAlias(struct cell_alias *a)
530 * Create new cell alias entry and update dynroot vnode.
536 afs_NewCellAlias(char *alias, char *cell)
538 struct cell_alias *tc;
540 ObtainSharedLock(&afs_xcell, 681);
541 if (afs_CellOrAliasExists_nl(alias)) {
542 ReleaseSharedLock(&afs_xcell);
546 UpgradeSToWLock(&afs_xcell, 682);
547 tc = (struct cell_alias *)afs_osi_Alloc(sizeof(struct cell_alias));
548 tc->alias = afs_strdup(alias);
549 tc->cell = afs_strdup(cell);
550 tc->next = afs_cellalias_head;
551 tc->index = afs_cellalias_index++;
552 afs_cellalias_head = tc;
553 ReleaseWriteLock(&afs_xcell);
555 afs_DynrootInvalidate();
560 * Actual cell list implementation
562 * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
563 * afs_RefreshCell: look up cell information in AFSDB if timeout expired
565 * afs_TraverseCells: execute a callback for each existing cell
566 * afs_TraverseCells_nl: same as above except without locking afs_xcell
567 * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
569 * afs_FindCellByName: return a cell with a given name, if it exists
570 * afs_FindCellByName_nl: same as above, without locking afs_xcell
571 * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
572 * afs_GetCell: return a cell with a given cell number
573 * afs_GetCellStale: same as GetCell, but does not try to refresh the data
574 * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
576 * afs_GetPrimaryCell: return the primary cell, if any
577 * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
578 * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
579 * afs_SetPrimaryCell: set the primary cell name to the given cell name
581 * afs_NewCell: create or update a cell entry
584 struct afs_q CellLRU; /* Export for kdump */
585 static char *afs_thiscell;
586 afs_int32 afs_cellindex; /* Export for kdump */
589 * Bump given cell up to the front of the LRU queue.
590 * \param c Cell to set.
593 afs_UpdateCellLRU(struct cell *c)
595 ObtainWriteLock(&afs_xcell, 100);
597 QAdd(&CellLRU, &c->lruq);
598 ReleaseWriteLock(&afs_xcell);
602 * Look up cell information in AFSDB if timeout expired
603 * \param ac Cell to be refreshed.
607 afs_RefreshCell(struct cell *ac)
609 if (ac->states & CNoAFSDB)
611 if (!ac->cellHosts[0] || (ac->timeout && ac->timeout <= osi_Time()))
612 afs_LookupAFSDB(ac->cellName);
616 * Execute a callback for each existing cell, without a lock on afs_xcell.
617 * Iterate on CellLRU, and execute a callback for each cell until given arguments are met.
618 * \see afs_TraverseCells
619 * \param cb Traversal callback for each cell.
620 * \param arg Callback arguments.
621 * \return Found data or NULL.
624 afs_TraverseCells_nl(void *(*cb) (struct cell *, void *), void *arg)
626 struct afs_q *cq, *tq;
630 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
633 /* This is assuming that a NULL return is acceptable. */
649 * Execute a callback for each existing cell, with a lock on afs_xcell.
650 * \see afs_TraverseCells_nl
651 * \param cb Traversal callback for each cell.
653 * \return Found data or NULL.
656 afs_TraverseCells(void *(*cb) (struct cell *, void *), void *arg)
660 ObtainReadLock(&afs_xcell);
661 ret = afs_TraverseCells_nl(cb, arg);
662 ReleaseReadLock(&afs_xcell);
668 * Useful traversal callback: Match by name.
670 * \param arg Cell name (compared with cell->cellName).
671 * \return Returns found cell or NULL.
674 afs_choose_cell_by_name(struct cell *cell, void *arg)
680 return strcmp(cell->cellName, (char *)arg) ? NULL : cell;
685 * Useful traversal callback: Match by handle.
687 * \param arg Cell handle (compared with cell->cellHandle).
688 * \return Returns found cell or NULL.
691 afs_choose_cell_by_handle(struct cell *cell, void *arg)
697 return memcmp(cell->cellHandle, (char *)arg, 16) ? NULL : cell;
702 * Useful traversal callback: Match by cell number.
704 * \param arg Cell number (compared with cell->cellNum).
705 * \return Returns found cell or NULL.
708 afs_choose_cell_by_num(struct cell *cell, void *arg)
710 return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
714 * Useful traversal callback: Match by index.
716 * \param arg Cell index (compared with cell->cellIndex).
717 * \return Returns found cell or NULL.
720 afs_choose_cell_by_index(struct cell *cell, void *arg)
722 return (cell->cellIndex == *((afs_int32 *) arg)) ? cell : NULL;
726 * Return a cell with a given name, if it exists. No lock version.
727 * Does not check AFSDB.
728 * \param acellName Cell name.
729 * \param locktype Type of lock to be used (not used).
733 afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
735 return afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
739 * Return a cell with a given name, if it exists.It uses locks.
740 * Does not check AFSDB.
741 * \param acellName Cell name.
742 * \param locktype Type of lock to be used.
746 afs_FindCellByName(char *acellName, afs_int32 locktype)
748 return afs_TraverseCells(&afs_choose_cell_by_name, acellName);
752 * Same as FindCellByName but tries AFSDB if not found.
753 * \param acellName Cell name.
754 * \param locktype Type of lock to be used.
758 afs_GetCellByName(char *acellName, afs_int32 locktype)
762 tc = afs_FindCellByName(acellName, locktype);
764 afs_LookupAFSDB(acellName);
765 tc = afs_FindCellByName(acellName, locktype);
768 afs_cellname_ref(tc->cnamep);
769 afs_UpdateCellLRU(tc);
777 * Return a cell with a given cell number.
778 * \param cellnum Cell number.
779 * \param locktype Lock to be used.
783 afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
786 struct cell_name *cn;
788 tc = afs_GetCellStale(cellnum, locktype);
792 ObtainReadLock(&afs_xcell);
793 cn = afs_cellname_lookup_id(cellnum);
794 ReleaseReadLock(&afs_xcell);
796 tc = afs_GetCellByName(cn->cellname, locktype);
802 * Same as GetCell, but does not try to refresh the data.
803 * \param cellnum Cell number.
804 * \param locktype What lock should be used.
808 afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
812 tc = afs_TraverseCells(&afs_choose_cell_by_num, &cellnum);
814 afs_cellname_ref(tc->cnamep);
815 afs_UpdateCellLRU(tc);
821 * Return a cell with a given index number (starting at 0). Update CellLRU as well.
823 * \param locktype Type of lock used.
827 afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
831 tc = afs_TraverseCells(&afs_choose_cell_by_index, &index);
833 afs_UpdateCellLRU(tc);
838 * Return a cell with a given handle..
840 * \param locktype Type of lock used.
844 afs_GetCellByHandle(void *handle, afs_int32 locktype)
848 tc = afs_TraverseCells(&afs_choose_cell_by_handle, handle);
850 afs_UpdateCellLRU(tc);
855 * Return primary cell, if any.
856 * \param locktype Type of lock used.
860 afs_GetPrimaryCell(afs_int32 locktype)
862 return afs_GetCellByName(afs_thiscell, locktype);
866 * Returns true if the given cell is the primary cell.
871 afs_IsPrimaryCell(struct cell *cell)
873 /* Simple safe checking */
876 } else if (!afs_thiscell) {
877 /* This is simply a safety net to avoid seg faults especially when
878 * using a user-space library. afs_SetPrimaryCell() should be set
879 * prior to this call. */
880 afs_SetPrimaryCell(cell->cellName);
883 return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
888 * Returns afs_IsPrimaryCell(afs_GetCell(cellnum)).
893 afs_IsPrimaryCellNum(afs_int32 cellnum)
898 tc = afs_GetCellStale(cellnum, READ_LOCK);
900 primary = afs_IsPrimaryCell(tc);
901 afs_PutCell(tc, READ_LOCK);
908 * Set the primary cell name to the given cell name.
909 * \param acellName Cell name.
910 * \return 0 for success, < 0 for error.
913 afs_SetPrimaryCell(char *acellName)
915 ObtainWriteLock(&afs_xcell, 691);
917 afs_osi_FreeStr(afs_thiscell);
918 afs_thiscell = afs_strdup(acellName);
919 ReleaseWriteLock(&afs_xcell);
924 * Create or update a cell entry.
925 * \param acellName Name of cell.
926 * \param acellHosts Array of hosts that this cell has.
927 * \param aflags Cell flags.
929 * \param fsport File server port.
930 * \param vlport Volume server port.
931 * \param timeout Cell timeout value, 0 means static AFSDB entry.
935 afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
936 char *linkedcname, u_short fsport, u_short vlport, int timeout)
938 struct cell *tc, *tcl = 0;
939 afs_int32 i, newc = 0, code = 0;
941 AFS_STATCNT(afs_NewCell);
943 ObtainWriteLock(&afs_xcell, 103);
945 tc = afs_FindCellByName_nl(acellName, READ_LOCK);
949 tc = (struct cell *)afs_osi_Alloc(sizeof(struct cell));
950 memset((char *)tc, 0, sizeof(*tc));
951 tc->cellName = afs_strdup(acellName);
952 tc->fsport = AFS_FSPORT;
953 tc->vlport = AFS_VLPORT;
954 AFS_MD5_String(tc->cellHandle, tc->cellName, strlen(tc->cellName));
955 RWLOCK_INIT(&tc->lock, "cell lock");
959 ObtainWriteLock(&tc->lock, 688);
961 /* If the cell we've found has the correct name but no timeout,
962 * and we're called with a non-zero timeout, bail out: never
963 * override static configuration entries with AFSDB ones.
964 * One exception: if the original cell entry had no servers,
965 * it must get servers from AFSDB.
967 if (timeout && !tc->timeout && tc->cellHosts[0]) {
968 code = EEXIST; /* This code is checked for in afs_LookupAFSDB */
972 /* we don't want to keep pinging old vlservers which were down,
973 * since they don't matter any more. It's easier to do this than
974 * to remove the server from its various hash tables. */
975 for (i = 0; i < MAXCELLHOSTS; i++) {
976 if (!tc->cellHosts[i])
978 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
979 tc->cellHosts[i]->flags |= SRVR_ISGONE;
987 if (aflags & CLinkedCell) {
992 tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
997 if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
998 tcl->lcellp->lcellp = (struct cell *)0;
999 tcl->lcellp->states &= ~CLinkedCell;
1004 tc->states |= aflags;
1005 tc->timeout = timeout;
1007 memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts));
1008 for (i = 0; i < MAXCELLHOSTS; i++) {
1009 /* Get server for each host and link this cell in.*/
1011 afs_uint32 temp = acellHosts[i];
1014 ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
1016 ts->flags &= ~SRVR_ISGONE;
1017 /* Set the server as a host of the new cell. */
1018 tc->cellHosts[i] = ts;
1019 afs_PutServer(ts, WRITE_LOCK);
1021 afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
1023 /* New cell: Build and add to LRU cell queue. */
1025 struct cell_name *cn;
1027 cn = afs_cellname_lookup_name(acellName);
1029 cn = afs_cellname_new(acellName, 0);
1032 tc->cellNum = cn->cellnum;
1033 tc->cellIndex = afs_cellindex++;
1034 afs_stats_cmperf.numCellsVisible++;
1035 QAdd(&CellLRU, &tc->lruq);
1038 ReleaseWriteLock(&tc->lock);
1039 ReleaseWriteLock(&afs_xcell);
1041 afs_DynrootInvalidate();
1046 afs_osi_FreeStr(tc->cellName);
1047 afs_osi_Free(tc, sizeof(struct cell));
1049 ReleaseWriteLock(&tc->lock);
1050 ReleaseWriteLock(&afs_xcell);
1055 * Miscellaneous stuff
1057 * afs_CellInit: perform whatever initialization is necessary
1058 * shutdown_cell: called on shutdown, should deallocate memory, etc
1059 * afs_RemoveCellEntry: remove a server from a cell's server list
1060 * afs_CellOrAliasExists: check if the given name exists as a cell or alias
1061 * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
1062 * afs_CellNumValid: check if a cell number is valid (also set the used flag)
1066 * Perform whatever initialization is necessary.
1071 RWLOCK_INIT(&afs_xcell, "afs_xcell");
1072 #ifdef AFS_AFSDB_ENV
1073 RWLOCK_INIT(&afsdb_client_lock, "afsdb_client_lock");
1074 RWLOCK_INIT(&afsdb_req_lock, "afsdb_req_lock");
1079 afs_cellalias_index = 0;
1083 * Called on shutdown, should deallocate memory, etc.
1088 struct afs_q *cq, *tq;
1091 RWLOCK_INIT(&afs_xcell, "afs_xcell");
1093 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1097 afs_osi_FreeStr(tc->cellName);
1098 afs_osi_Free(tc, sizeof(struct cell));
1103 struct cell_name *cn = afs_cellname_head;
1106 struct cell_name *next = cn->next;
1108 afs_osi_FreeStr(cn->cellname);
1109 afs_osi_Free(cn, sizeof(struct cell_name));
1116 * Remove a server from a cell's server list.
1117 * \param srvp Server to be removed.
1121 afs_RemoveCellEntry(struct server *srvp)
1130 /* Remove the server structure from the cell list - if there */
1131 ObtainWriteLock(&tc->lock, 200);
1132 for (j = k = 0; j < MAXCELLHOSTS; j++) {
1133 if (!tc->cellHosts[j])
1135 if (tc->cellHosts[j] != srvp) {
1136 tc->cellHosts[k++] = tc->cellHosts[j];
1140 /* What do we do if we remove the last one? */
1142 for (; k < MAXCELLHOSTS; k++) {
1143 tc->cellHosts[k] = 0;
1145 ReleaseWriteLock(&tc->lock);
1149 * Check if the given name exists as a cell or alias. Does not lock afs_xcell.
1154 afs_CellOrAliasExists_nl(char *aname)
1157 struct cell_alias *ca;
1159 c = afs_FindCellByName_nl(aname, READ_LOCK);
1161 afs_PutCell(c, READ_LOCK);
1165 ca = afs_FindCellAlias(aname);
1167 afs_PutCellAlias(ca);
1175 * Check if the given name exists as a cell or alias. Locks afs_xcell.
1180 afs_CellOrAliasExists(char *aname)
1184 ObtainReadLock(&afs_xcell);
1185 ret = afs_CellOrAliasExists_nl(aname);
1186 ReleaseReadLock(&afs_xcell);
1192 * Check if a cell number is valid (also set the used flag).
1194 * \return 1 - true, 0 - false
1197 afs_CellNumValid(afs_int32 cellnum)
1199 struct cell_name *cn;
1201 ObtainReadLock(&afs_xcell);
1202 cn = afs_cellname_lookup_id(cellnum);
1203 ReleaseReadLock(&afs_xcell);