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 #if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV) || defined(RXK_UPCALL_ENV)
61 afs_termState
= AFSOP_STOP_RXEVENT
;
63 afs_termState
= AFSOP_STOP_COMPLETE
;
65 afs_osi_Wakeup(&afs_termState
);
70 * \brief Entry point for user-space AFSDB request handler.
71 * Reads cell data from kerlenMsg and add new cell, or alias.
72 * \param acellName Cell name. If a cell is found, it's name will be filled in here.
73 * \param acellNameLen Cell name length.
74 * \param kernelMsg Buffer containing data about host count, time out, and cell hosts ids.
75 * \return 0 for success, < 0 for error.
78 afs_AFSDBHandler(char *acellName
, int acellNameLen
, afs_int32
* kernelMsg
)
80 afs_int32 timeout
, code
;
81 afs_int32 cellHosts
[AFS_MAXCELLHOSTS
];
83 if (afsdb_handler_shutdown
)
85 afsdb_handler_running
= 1;
87 ObtainSharedLock(&afsdb_req_lock
, 683);
88 if (afsdb_req
.pending
) {
91 UpgradeSToWLock(&afsdb_req_lock
, 684);
92 hostCount
= kernelMsg
[0];
93 timeout
= kernelMsg
[1];
95 timeout
+= osi_Time();
97 for (i
= 0; i
< AFS_MAXCELLHOSTS
; i
++) {
101 cellHosts
[i
] = kernelMsg
[2 + i
];
105 code
= afs_NewCell(acellName
, cellHosts
, CNoSUID
, NULL
, 0, 0,
108 if (!hostCount
|| (code
&& code
!= EEXIST
))
109 /* null out the cellname if the lookup failed */
110 afsdb_req
.cellname
= NULL
;
112 /* If we found an alias, create it */
113 if (afs_strcasecmp(afsdb_req
.cellname
, acellName
))
114 afs_NewCellAlias(afsdb_req
.cellname
, acellName
);
116 /* Request completed, wake up the relevant thread */
117 afsdb_req
.pending
= 0;
118 afsdb_req
.complete
= 1;
119 afs_osi_Wakeup(&afsdb_req
);
120 ConvertWToSLock(&afsdb_req_lock
);
122 ConvertSToRLock(&afsdb_req_lock
);
124 /* Wait for a request */
125 while (afsdb_req
.pending
== 0 && afs_termState
!= AFSOP_STOP_AFSDB
) {
126 ReleaseReadLock(&afsdb_req_lock
);
127 afs_osi_Sleep(&afsdb_req
);
128 ObtainReadLock(&afsdb_req_lock
);
131 /* Check if we're shutting down */
132 if (afs_termState
== AFSOP_STOP_AFSDB
) {
133 ReleaseReadLock(&afsdb_req_lock
);
135 /* Inform anyone waiting for us that we're going away */
136 afsdb_handler_shutdown
= 1;
137 afsdb_handler_running
= 0;
138 afs_osi_Wakeup(&afsdb_req
);
140 afs_termState
= AFSOP_STOP_RXEVENT
;
141 afs_osi_Wakeup(&afs_termState
);
145 /* Return the lookup request to userspace */
146 strncpy(acellName
, afsdb_req
.cellname
, acellNameLen
);
147 ReleaseReadLock(&afsdb_req_lock
);
152 * \brief Query the AFSDB handler and wait for response.
154 * \return 0 for success. < 0 is error.
157 afs_GetCellHostsAFSDB(char *acellName
)
160 if (!afsdb_handler_running
)
163 ObtainWriteLock(&afsdb_client_lock
, 685);
164 ObtainWriteLock(&afsdb_req_lock
, 686);
166 afsdb_req
.cellname
= acellName
;
168 afsdb_req
.complete
= 0;
169 afsdb_req
.pending
= 1;
170 afs_osi_Wakeup(&afsdb_req
);
171 ConvertWToRLock(&afsdb_req_lock
);
173 while (afsdb_handler_running
&& !afsdb_req
.complete
) {
174 ReleaseReadLock(&afsdb_req_lock
);
175 afs_osi_Sleep(&afsdb_req
);
176 ObtainReadLock(&afsdb_req_lock
);
179 ReleaseReadLock(&afsdb_req_lock
);
180 ReleaseWriteLock(&afsdb_client_lock
);
182 if (afsdb_req
.cellname
) {
190 * Look up AFSDB for given cell name and create locally.
191 * \param acellName Cell name.
194 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
);
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
= afs_osi_Alloc(sizeof(*cn
));
237 osi_Assert(cn
!= NULL
);
238 cn
->next
= afs_cellname_head
;
239 cn
->cellnum
= cellnum
;
240 cn
->cellname
= afs_strdup(name
);
242 afs_cellname_head
= cn
;
244 if (cellnum
>= afs_cellnum_next
)
245 afs_cellnum_next
= cellnum
+ 1;
251 * Look up a cell name by id.
255 static struct cell_name
*
256 afs_cellname_lookup_id(afs_int32 cellnum
)
258 struct cell_name
*cn
;
260 for (cn
= afs_cellname_head
; cn
; cn
= cn
->next
)
261 if (cn
->cellnum
== cellnum
)
268 * Look up a cell name.
269 * \param name Cell name.
272 static struct cell_name
*
273 afs_cellname_lookup_name(char *name
)
275 struct cell_name
*cn
;
277 for (cn
= afs_cellname_head
; cn
; cn
= cn
->next
)
278 if (strcmp(cn
->cellname
, name
) == 0)
285 * Note that this cell name was referenced somewhere.
289 afs_cellname_ref(struct cell_name
*cn
)
293 afs_cellname_dirty
= 1;
298 * \brief Load the list of cells from given inode.
299 * \param inode Source inode.
301 * \return 0 for success. < 0 for error.
304 afs_cellname_init(afs_dcache_id_t
*inode
, int lookupcode
)
306 struct osi_file
*tfile
;
309 ObtainWriteLock(&afs_xcell
, 692);
311 afs_cellnum_next
= 1;
312 afs_cellname_dirty
= 0;
314 if (cacheDiskType
== AFS_FCACHE_TYPE_MEM
) {
315 ReleaseWriteLock(&afs_xcell
);
319 ReleaseWriteLock(&afs_xcell
);
323 tfile
= osi_UFSOpen(inode
);
325 ReleaseWriteLock(&afs_xcell
);
329 afs_copy_inode(&afs_cellname_inode
, inode
);
330 afs_cellname_inode_set
= 1;
333 afs_int32 cellnum
, clen
, magic
;
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 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
= afs_osi_Alloc(sizeof(struct cell_alias
));
519 osi_Assert(tc
!= NULL
);
520 tc
->alias
= afs_strdup(alias
);
521 tc
->cell
= afs_strdup(cell
);
522 tc
->next
= afs_cellalias_head
;
523 tc
->index
= afs_cellalias_index
++;
524 afs_cellalias_head
= tc
;
525 ReleaseWriteLock(&afs_xcell
);
527 afs_DynrootInvalidate();
532 * Actual cell list implementation
534 * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
535 * afs_RefreshCell: look up cell information in AFSDB if timeout expired
537 * afs_TraverseCells: execute a callback for each existing cell
538 * afs_TraverseCells_nl: same as above except without locking afs_xcell
539 * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
541 * afs_FindCellByName: return a cell with a given name, if it exists
542 * afs_FindCellByName_nl: same as above, without locking afs_xcell
543 * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
544 * afs_GetCell: return a cell with a given cell number
545 * afs_GetCellStale: same as GetCell, but does not try to refresh the data
546 * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
548 * afs_GetPrimaryCell: return the primary cell, if any
549 * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
550 * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
551 * afs_SetPrimaryCell: set the primary cell name to the given cell name
553 * afs_NewCell: create or update a cell entry
556 struct afs_q CellLRU
; /* Export for kdump */
557 static char *afs_thiscell
= NULL
;
558 afs_int32 afs_cellindex
; /* Export for kdump */
561 * Bump given cell up to the front of the LRU queue.
562 * \param c Cell to set.
565 afs_UpdateCellLRU(struct cell
*c
)
567 ObtainWriteLock(&afs_xcell
, 100);
569 QAdd(&CellLRU
, &c
->lruq
);
570 ReleaseWriteLock(&afs_xcell
);
574 * Look up cell information in AFSDB if timeout expired
575 * \param ac Cell to be refreshed.
579 afs_RefreshCell(struct cell
*ac
)
581 if (ac
->states
& CNoAFSDB
)
583 if (!ac
->cellHosts
[0] || (ac
->timeout
&& ac
->timeout
<= osi_Time()))
584 afs_LookupAFSDB(ac
->cellName
);
588 * Execute a callback for each existing cell, without a lock on afs_xcell.
589 * Iterate on CellLRU, and execute a callback for each cell until given arguments are met.
590 * \see afs_TraverseCells
591 * \param cb Traversal callback for each cell.
592 * \param arg Callback arguments.
593 * \return Found data or NULL.
596 afs_TraverseCells_nl(void *(*cb
) (struct cell
*, void *), void *arg
)
598 struct afs_q
*cq
, *tq
;
602 for (cq
= CellLRU
.next
; cq
!= &CellLRU
; cq
= tq
) {
605 /* This is assuming that a NULL return is acceptable. */
621 * Execute a callback for each existing cell, with a lock on afs_xcell.
622 * \see afs_TraverseCells_nl
623 * \param cb Traversal callback for each cell.
625 * \return Found data or NULL.
628 afs_TraverseCells(void *(*cb
) (struct cell
*, void *), void *arg
)
632 ObtainReadLock(&afs_xcell
);
633 ret
= afs_TraverseCells_nl(cb
, arg
);
634 ReleaseReadLock(&afs_xcell
);
640 * Useful traversal callback: Match by name.
642 * \param arg Cell name (compared with cell->cellName).
643 * \return Returns found cell or NULL.
646 afs_choose_cell_by_name(struct cell
*cell
, void *arg
)
652 return strcmp(cell
->cellName
, (char *)arg
) ? NULL
: cell
;
657 * Useful traversal callback: Match by handle.
659 * \param arg Cell handle (compared with cell->cellHandle).
660 * \return Returns found cell or NULL.
663 afs_choose_cell_by_handle(struct cell
*cell
, void *arg
)
669 return memcmp(cell
->cellHandle
, (char *)arg
, 16) ? NULL
: cell
;
674 * Useful traversal callback: Match by cell number.
676 * \param arg Cell number (compared with cell->cellNum).
677 * \return Returns found cell or NULL.
680 afs_choose_cell_by_num(struct cell
*cell
, void *arg
)
682 return (cell
->cellNum
== *((afs_int32
*) arg
)) ? cell
: NULL
;
686 * Useful traversal callback: Match by index.
688 * \param arg Cell index (compared with cell->cellIndex).
689 * \return Returns found cell or NULL.
692 afs_choose_cell_by_index(struct cell
*cell
, void *arg
)
694 return (cell
->cellIndex
== *((afs_int32
*) arg
)) ? cell
: NULL
;
698 * Return a cell with a given name, if it exists. No lock version.
699 * Does not check AFSDB.
700 * \param acellName Cell name.
701 * \param locktype Type of lock to be used (not used).
705 afs_FindCellByName_nl(char *acellName
, afs_int32 locktype
)
707 return afs_TraverseCells_nl(&afs_choose_cell_by_name
, acellName
);
711 * Return a cell with a given name, if it exists.It uses locks.
712 * Does not check AFSDB.
713 * \param acellName Cell name.
714 * \param locktype Type of lock to be used.
718 afs_FindCellByName(char *acellName
, afs_int32 locktype
)
720 return afs_TraverseCells(&afs_choose_cell_by_name
, acellName
);
724 * Same as FindCellByName but tries AFSDB if not found.
725 * \param acellName Cell name.
726 * \param locktype Type of lock to be used.
730 afs_GetCellByName(char *acellName
, afs_int32 locktype
)
734 tc
= afs_FindCellByName(acellName
, locktype
);
736 afs_LookupAFSDB(acellName
);
737 tc
= afs_FindCellByName(acellName
, locktype
);
740 afs_cellname_ref(tc
->cnamep
);
741 afs_UpdateCellLRU(tc
);
749 * Return a cell with a given cell number.
750 * \param cellnum Cell number.
751 * \param locktype Lock to be used.
755 afs_GetCell(afs_int32 cellnum
, afs_int32 locktype
)
758 struct cell_name
*cn
;
760 tc
= afs_GetCellStale(cellnum
, locktype
);
764 ObtainReadLock(&afs_xcell
);
765 cn
= afs_cellname_lookup_id(cellnum
);
766 ReleaseReadLock(&afs_xcell
);
768 tc
= afs_GetCellByName(cn
->cellname
, locktype
);
774 * Same as GetCell, but does not try to refresh the data.
775 * \param cellnum Cell number.
776 * \param locktype What lock should be used.
780 afs_GetCellStale(afs_int32 cellnum
, afs_int32 locktype
)
784 tc
= afs_TraverseCells(&afs_choose_cell_by_num
, &cellnum
);
786 afs_cellname_ref(tc
->cnamep
);
787 afs_UpdateCellLRU(tc
);
793 * Return a cell with a given index number (starting at 0). Update CellLRU as well.
795 * \param locktype Type of lock used.
799 afs_GetCellByIndex(afs_int32 index
, afs_int32 locktype
)
803 tc
= afs_TraverseCells(&afs_choose_cell_by_index
, &index
);
805 afs_UpdateCellLRU(tc
);
810 * Return a cell with a given handle..
812 * \param locktype Type of lock used.
816 afs_GetCellByHandle(void *handle
, afs_int32 locktype
)
820 tc
= afs_TraverseCells(&afs_choose_cell_by_handle
, handle
);
822 afs_UpdateCellLRU(tc
);
827 * Return primary cell, if any.
828 * \param locktype Type of lock used.
832 afs_GetPrimaryCell(afs_int32 locktype
)
834 return afs_GetCellByName(afs_thiscell
, locktype
);
838 * Return number of the primary cell.
840 * Cell number, or 0 if primary cell not found
843 afs_GetPrimaryCellNum(void)
846 afs_int32 cellNum
= 0;
847 cell
= afs_GetPrimaryCell(READ_LOCK
);
849 cellNum
= cell
->cellNum
;
850 afs_PutCell(cell
, READ_LOCK
);
856 * Returns true if the given cell is the primary cell.
861 afs_IsPrimaryCell(struct cell
*cell
)
863 /* Simple safe checking */
866 } else if (!afs_thiscell
) {
867 /* This is simply a safety net to avoid seg faults especially when
868 * using a user-space library. afs_SetPrimaryCell() should be set
869 * prior to this call. */
870 afs_SetPrimaryCell(cell
->cellName
);
873 return strcmp(cell
->cellName
, afs_thiscell
) ? 0 : 1;
878 * Returns afs_IsPrimaryCell(afs_GetCell(cellnum)).
883 afs_IsPrimaryCellNum(afs_int32 cellnum
)
888 tc
= afs_GetCellStale(cellnum
, READ_LOCK
);
890 primary
= afs_IsPrimaryCell(tc
);
891 afs_PutCell(tc
, READ_LOCK
);
898 * Set the primary cell name to the given cell name.
899 * \param acellName Cell name.
900 * \return 0 for success, < 0 for error.
903 afs_SetPrimaryCell(char *acellName
)
905 ObtainWriteLock(&afs_xcell
, 691);
907 afs_osi_FreeStr(afs_thiscell
);
908 afs_thiscell
= afs_strdup(acellName
);
909 ReleaseWriteLock(&afs_xcell
);
914 * Create or update a cell entry.
915 * \param acellName Name of cell.
916 * \param acellHosts Array of hosts that this cell has.
917 * \param aflags Cell flags.
919 * \param fsport File server port.
920 * \param vlport Volume server port.
921 * \param timeout Cell timeout value, 0 means static AFSDB entry.
925 afs_NewCell(char *acellName
, afs_int32
* acellHosts
, int aflags
,
926 char *linkedcname
, u_short fsport
, u_short vlport
, int timeout
)
928 struct cell
*tc
, *tcl
= 0;
929 afs_int32 i
, newc
= 0, code
= 0;
932 AFS_STATCNT(afs_NewCell
);
934 ObtainWriteLock(&afs_xcell
, 103);
936 tc
= afs_FindCellByName_nl(acellName
, READ_LOCK
);
940 tc
= afs_osi_Alloc(sizeof(struct cell
));
941 osi_Assert(tc
!= NULL
);
942 memset(tc
, 0, sizeof(*tc
));
943 tc
->cellName
= afs_strdup(acellName
);
944 tc
->fsport
= AFS_FSPORT
;
945 tc
->vlport
= AFS_VLPORT
;
947 MD5_Update(&m
, tc
->cellName
, strlen(tc
->cellName
));
948 MD5_Final(tc
->cellHandle
, &m
);
949 AFS_RWLOCK_INIT(&tc
->lock
, "cell lock");
953 ObtainWriteLock(&tc
->lock
, 688);
955 /* If the cell we've found has the correct name but no timeout,
956 * and we're called with a non-zero timeout, bail out: never
957 * override static configuration entries with AFSDB ones.
958 * One exception: if the original cell entry had no servers,
959 * it must get servers from AFSDB.
961 if (timeout
&& !tc
->timeout
&& tc
->cellHosts
[0]) {
962 code
= EEXIST
; /* This code is checked for in afs_LookupAFSDB */
966 /* we don't want to keep pinging old vlservers which were down,
967 * since they don't matter any more. It's easier to do this than
968 * to remove the server from its various hash tables. */
969 for (i
= 0; i
< AFS_MAXCELLHOSTS
; i
++) {
970 if (!tc
->cellHosts
[i
])
972 tc
->cellHosts
[i
]->flags
&= ~SRVR_ISDOWN
;
973 tc
->cellHosts
[i
]->flags
|= SRVR_ISGONE
;
981 if (aflags
& CLinkedCell
) {
986 tcl
= afs_FindCellByName_nl(linkedcname
, READ_LOCK
);
991 if (tcl
->lcellp
) { /* XXX Overwriting if one existed before! XXX */
992 tcl
->lcellp
->lcellp
= (struct cell
*)0;
993 tcl
->lcellp
->states
&= ~CLinkedCell
;
998 tc
->states
|= aflags
;
999 tc
->timeout
= timeout
;
1001 memset(tc
->cellHosts
, 0, sizeof(tc
->cellHosts
));
1002 for (i
= 0; i
< AFS_MAXCELLHOSTS
; i
++) {
1003 /* Get server for each host and link this cell in.*/
1005 afs_uint32 temp
= acellHosts
[i
];
1008 ts
= afs_GetServer(&temp
, 1, 0, tc
->vlport
, WRITE_LOCK
, NULL
, 0, NULL
);
1010 ts
->flags
&= ~SRVR_ISGONE
;
1011 /* Set the server as a host of the new cell. */
1012 tc
->cellHosts
[i
] = ts
;
1013 afs_PutServer(ts
, WRITE_LOCK
);
1015 afs_SortServers(tc
->cellHosts
, AFS_MAXCELLHOSTS
); /* randomize servers */
1017 /* New cell: Build and add to LRU cell queue. */
1019 struct cell_name
*cn
;
1021 cn
= afs_cellname_lookup_name(acellName
);
1023 cn
= afs_cellname_new(acellName
, 0);
1026 tc
->cellNum
= cn
->cellnum
;
1027 tc
->cellIndex
= afs_cellindex
++;
1028 afs_stats_cmperf
.numCellsVisible
++;
1029 QAdd(&CellLRU
, &tc
->lruq
);
1032 ReleaseWriteLock(&tc
->lock
);
1033 ReleaseWriteLock(&afs_xcell
);
1035 if (!(aflags
& CHush
))
1036 afs_DynrootInvalidate();
1040 ReleaseWriteLock(&tc
->lock
);
1043 /* If we're a new cell, nobody else can see us, so doing this
1044 * after lock release is safe */
1045 afs_osi_FreeStr(tc
->cellName
);
1046 afs_osi_Free(tc
, sizeof(struct cell
));
1049 ReleaseWriteLock(&afs_xcell
);
1054 * Miscellaneous stuff
1056 * afs_CellInit: perform whatever initialization is necessary
1057 * shutdown_cell: called on shutdown, should deallocate memory, etc
1058 * afs_RemoveCellEntry: remove a server from a cell's server list
1059 * afs_CellOrAliasExists: check if the given name exists as a cell or alias
1060 * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
1061 * afs_CellNumValid: check if a cell number is valid (also set the used flag)
1065 * Perform whatever initialization is necessary.
1070 static char CellInit_done
= 0;
1077 AFS_RWLOCK_INIT(&afs_xcell
, "afs_xcell");
1078 AFS_RWLOCK_INIT(&afsdb_client_lock
, "afsdb_client_lock");
1079 AFS_RWLOCK_INIT(&afsdb_req_lock
, "afsdb_req_lock");
1083 afs_cellalias_index
= 0;
1087 * Called on shutdown, should deallocate memory, etc.
1092 struct afs_q
*cq
, *tq
;
1095 #ifdef AFS_CACHE_VNODE_PATH
1096 if (cacheDiskType
!= AFS_FCACHE_TYPE_MEM
) {
1097 afs_osi_FreeStr(afs_cellname_inode
.ufs
);
1100 AFS_RWLOCK_INIT(&afs_xcell
, "afs_xcell");
1102 for (cq
= CellLRU
.next
; cq
!= &CellLRU
; cq
= tq
) {
1106 afs_osi_FreeStr(tc
->cellName
);
1107 afs_osi_Free(tc
, sizeof(struct cell
));
1112 struct cell_name
*cn
= afs_cellname_head
;
1115 struct cell_name
*next
= cn
->next
;
1117 afs_osi_FreeStr(cn
->cellname
);
1118 afs_osi_Free(cn
, sizeof(struct cell_name
));
1125 * Remove a server from a cell's server list.
1126 * \param srvp Server to be removed.
1130 afs_RemoveCellEntry(struct server
*srvp
)
1139 /* Remove the server structure from the cell list - if there */
1140 ObtainWriteLock(&tc
->lock
, 200);
1141 for (j
= k
= 0; j
< AFS_MAXCELLHOSTS
; j
++) {
1142 if (!tc
->cellHosts
[j
])
1144 if (tc
->cellHosts
[j
] != srvp
) {
1145 tc
->cellHosts
[k
++] = tc
->cellHosts
[j
];
1149 /* What do we do if we remove the last one? */
1151 for (; k
< AFS_MAXCELLHOSTS
; k
++) {
1152 tc
->cellHosts
[k
] = 0;
1154 ReleaseWriteLock(&tc
->lock
);
1158 * Check if the given name exists as a cell or alias. Does not lock afs_xcell.
1163 afs_CellOrAliasExists_nl(char *aname
)
1166 struct cell_alias
*ca
;
1168 c
= afs_FindCellByName_nl(aname
, READ_LOCK
);
1170 afs_PutCell(c
, READ_LOCK
);
1174 ca
= afs_FindCellAlias(aname
);
1176 afs_PutCellAlias(ca
);
1184 * Check if the given name exists as a cell or alias. Locks afs_xcell.
1189 afs_CellOrAliasExists(char *aname
)
1193 ObtainReadLock(&afs_xcell
);
1194 ret
= afs_CellOrAliasExists_nl(aname
);
1195 ReleaseReadLock(&afs_xcell
);
1201 * Check if a cell number is valid (also set the used flag).
1203 * \return 1 - true, 0 - false
1206 afs_CellNumValid(afs_int32 cellnum
)
1208 struct cell_name
*cn
;
1210 ObtainReadLock(&afs_xcell
);
1211 cn
= afs_cellname_lookup_id(cellnum
);
1212 ReleaseReadLock(&afs_xcell
);