/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
* Implements:
*/
#include <afsconfig.h>
-#include "../afs/param.h"
+#include "afs/param.h"
-RCSID("$Header$");
-#include "../afs/stds.h"
-#include "../afs/sysincludes.h" /* Standard vendor system headers */
-#include "../afs/afsincludes.h" /* Afs-based standard headers */
-#include "../afs/afs_stats.h" /* afs statistics */
-#include "../afs/afs_osi.h"
+#include "afs/stds.h"
+#include "afs/sysincludes.h" /* Standard vendor system headers */
+#include "afsincludes.h" /* Afs-based standard headers */
+#include "afs/afs_stats.h" /* afs statistics */
+#include "afs/afs_osi.h"
+#include "hcrypto/md5.h"
/* Local variables. */
afs_rwlock_t afs_xcell; /* Export for cmdebug peeking at locks */
* afs_LookupAFSDB: look up AFSDB for given cell name and create locally
*/
-#ifdef AFS_AFSDB_ENV
-static afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
+afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
+afs_rwlock_t afsdb_req_lock; /* Serializes client requests */
static char afsdb_handler_running; /* Protected by GLOCK */
static char afsdb_handler_shutdown; /* Protected by GLOCK */
+/* from cellconfig.h */
+#define MAXCELLCHARS 64
static struct {
- afs_rwlock_t lock;
+ /* lock moved to afsdb_req_lock for cmdebug */
char pending;
char complete;
char *cellname;
- afs_int32 *cellhosts;
- int *timeout;
- char **realname;
} afsdb_req;
-void afs_StopAFSDB()
+/*!
+ * Terminate the AFSDB handler, used on shutdown.
+ */
+void
+afs_StopAFSDB(void)
{
if (afsdb_handler_running) {
afs_osi_Wakeup(&afsdb_req);
} else {
afsdb_handler_shutdown = 1;
+#if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV) || defined(RXK_UPCALL_ENV)
afs_termState = AFSOP_STOP_RXEVENT;
+#else
+ afs_termState = AFSOP_STOP_COMPLETE;
+#endif
+ afs_osi_Wakeup(&afs_termState);
}
}
-int afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 *kernelMsg)
+/*!
+ * \brief Entry point for user-space AFSDB request handler.
+ * Reads cell data from kerlenMsg and add new cell, or alias.
+ * \param acellName Cell name. If a cell is found, it's name will be filled in here.
+ * \param acellNameLen Cell name length.
+ * \param kernelMsg Buffer containing data about host count, time out, and cell hosts ids.
+ * \return 0 for success, < 0 for error.
+ */
+int
+afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 * kernelMsg)
{
- if (afsdb_handler_shutdown) return -2;
+ afs_int32 timeout, code;
+ afs_int32 cellHosts[AFS_MAXCELLHOSTS];
+
+ if (afsdb_handler_shutdown)
+ return -2;
afsdb_handler_running = 1;
- ObtainSharedLock(&afsdb_req.lock, 683);
+ ObtainSharedLock(&afsdb_req_lock, 683);
if (afsdb_req.pending) {
int i, hostCount;
- UpgradeSToWLock(&afsdb_req.lock, 684);
+ UpgradeSToWLock(&afsdb_req_lock, 684);
hostCount = kernelMsg[0];
- *afsdb_req.timeout = kernelMsg[1];
- if (*afsdb_req.timeout) *afsdb_req.timeout += osi_Time();
- *afsdb_req.realname = afs_strdup(acellName);
+ timeout = kernelMsg[1];
+ if (timeout)
+ timeout += osi_Time();
- for (i=0; i<MAXCELLHOSTS; i++) {
+ for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
if (i >= hostCount)
- afsdb_req.cellhosts[i] = 0;
+ cellHosts[i] = 0;
else
- afsdb_req.cellhosts[i] = kernelMsg[2+i];
+ cellHosts[i] = kernelMsg[2 + i];
}
+ if (hostCount)
+ code = afs_NewCell(acellName, cellHosts, CNoSUID, NULL, 0, 0,
+ timeout);
+
+ if (!hostCount || (code && code != EEXIST))
+ /* null out the cellname if the lookup failed */
+ afsdb_req.cellname = NULL;
+ else
+ /* If we found an alias, create it */
+ if (afs_strcasecmp(afsdb_req.cellname, acellName))
+ afs_NewCellAlias(afsdb_req.cellname, acellName);
+
/* Request completed, wake up the relevant thread */
afsdb_req.pending = 0;
afsdb_req.complete = 1;
afs_osi_Wakeup(&afsdb_req);
- ConvertWToSLock(&afsdb_req.lock);
+ ConvertWToSLock(&afsdb_req_lock);
}
- ConvertSToRLock(&afsdb_req.lock);
+ ConvertSToRLock(&afsdb_req_lock);
/* Wait for a request */
while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
- ReleaseReadLock(&afsdb_req.lock);
+ ReleaseReadLock(&afsdb_req_lock);
afs_osi_Sleep(&afsdb_req);
- ObtainReadLock(&afsdb_req.lock);
+ ObtainReadLock(&afsdb_req_lock);
}
/* Check if we're shutting down */
if (afs_termState == AFSOP_STOP_AFSDB) {
- ReleaseReadLock(&afsdb_req.lock);
+ ReleaseReadLock(&afsdb_req_lock);
/* Inform anyone waiting for us that we're going away */
afsdb_handler_shutdown = 1;
return -2;
}
- /* Return the lookup request to userspace */
+ /* Return the lookup request to userspace */
strncpy(acellName, afsdb_req.cellname, acellNameLen);
- ReleaseReadLock(&afsdb_req.lock);
+ ReleaseReadLock(&afsdb_req_lock);
return 0;
}
-static int afs_GetCellHostsAFSDB(char *acellName, afs_int32 *acellHosts,
- int *timeout, char **realName)
+/*!
+ * \brief Query the AFSDB handler and wait for response.
+ * \param acellName
+ * \return 0 for success. < 0 is error.
+ */
+static int
+afs_GetCellHostsAFSDB(char *acellName)
{
AFS_ASSERT_GLOCK();
- if (!afsdb_handler_running) return ENOENT;
+ if (!afsdb_handler_running)
+ return ENOENT;
ObtainWriteLock(&afsdb_client_lock, 685);
- ObtainWriteLock(&afsdb_req.lock, 686);
+ ObtainWriteLock(&afsdb_req_lock, 686);
- *acellHosts = 0;
afsdb_req.cellname = acellName;
- afsdb_req.cellhosts = acellHosts;
- afsdb_req.timeout = timeout;
- afsdb_req.realname = realName;
afsdb_req.complete = 0;
afsdb_req.pending = 1;
afs_osi_Wakeup(&afsdb_req);
- ConvertWToRLock(&afsdb_req.lock);
+ ConvertWToRLock(&afsdb_req_lock);
while (afsdb_handler_running && !afsdb_req.complete) {
- ReleaseReadLock(&afsdb_req.lock);
+ ReleaseReadLock(&afsdb_req_lock);
afs_osi_Sleep(&afsdb_req);
- ObtainReadLock(&afsdb_req.lock);
+ ObtainReadLock(&afsdb_req_lock);
};
- ReleaseReadLock(&afsdb_req.lock);
+
+ ReleaseReadLock(&afsdb_req_lock);
ReleaseWriteLock(&afsdb_client_lock);
- if (*acellHosts)
+ if (afsdb_req.cellname) {
return 0;
- else
+ } else
return ENOENT;
}
-#endif
-void afs_LookupAFSDB(char *acellName)
-{
-#ifdef AFS_AFSDB_ENV
- afs_int32 cellHosts[MAXCELLHOSTS];
- char *realName = NULL;
- int code, timeout;
-
- code = afs_GetCellHostsAFSDB(acellName, cellHosts, &timeout, &realName);
- if (code) goto done;
- code = afs_NewCell(realName, cellHosts, CNoSUID, NULL, 0, 0, timeout);
- if (code) goto done;
-
- /* If we found an alias, create it */
- if (afs_strcasecmp(acellName, realName))
- afs_NewCellAlias(acellName, realName);
-
-done:
- if (realName)
- afs_osi_FreeStr(realName);
-#endif
+
+/*!
+ * Look up AFSDB for given cell name and create locally.
+ * \param acellName Cell name.
+ */
+void
+afs_LookupAFSDB(char *acellName)
+{
+ int code;
+ char *cellName = afs_strdup(acellName);
+
+ code = afs_GetCellHostsAFSDB(cellName);
+ afs_Trace2(afs_iclSetp, CM_TRACE_AFSDB, ICL_TYPE_STRING, cellName,
+ ICL_TYPE_INT32, code);
+ afs_osi_FreeStr(cellName);
}
/*
*/
struct cell_name *afs_cellname_head; /* Export for kdump */
-static ino_t afs_cellname_inode;
+static afs_dcache_id_t afs_cellname_inode;
static int afs_cellname_inode_set;
static int afs_cellname_dirty;
static afs_int32 afs_cellnum_next;
-static struct cell_name *afs_cellname_new(char *name, afs_int32 cellnum)
+/*!
+ * Create a new cell name, optional cell number.
+ * \param name Name of cell.
+ * \param cellnum Cellname number.
+ * \return Initialized structure.
+ */
+static struct cell_name *
+afs_cellname_new(char *name, afs_int32 cellnum)
{
struct cell_name *cn;
if (cellnum == 0)
cellnum = afs_cellnum_next;
- cn = (struct cell_name *) afs_osi_Alloc(sizeof(*cn));
+ cn = afs_osi_Alloc(sizeof(*cn));
+ osi_Assert(cn != NULL);
cn->next = afs_cellname_head;
cn->cellnum = cellnum;
cn->cellname = afs_strdup(name);
return cn;
}
-static struct cell_name *afs_cellname_lookup_id(afs_int32 cellnum)
+/*!
+ * Look up a cell name by id.
+ * \param cellnum
+ * \return
+ */
+static struct cell_name *
+afs_cellname_lookup_id(afs_int32 cellnum)
{
struct cell_name *cn;
return NULL;
}
-static struct cell_name *afs_cellname_lookup_name(char *name)
+/*!
+ * Look up a cell name.
+ * \param name Cell name.
+ * \return
+ */
+static struct cell_name *
+afs_cellname_lookup_name(char *name)
{
struct cell_name *cn;
return NULL;
}
-static void afs_cellname_ref(struct cell_name *cn)
+/*!
+ * Note that this cell name was referenced somewhere.
+ * \param cn
+ */
+static void
+afs_cellname_ref(struct cell_name *cn)
{
if (!cn->used) {
cn->used = 1;
}
}
-int afs_cellname_init(ino_t inode, int lookupcode)
+/*!
+ * \brief Load the list of cells from given inode.
+ * \param inode Source inode.
+ * \param lookupcode
+ * \return 0 for success. < 0 for error.
+ */
+int
+afs_cellname_init(afs_dcache_id_t *inode, int lookupcode)
{
struct osi_file *tfile;
int cc, off = 0;
return EIO;
}
- afs_cellname_inode = inode;
+ afs_copy_inode(&afs_cellname_inode, inode);
afs_cellname_inode_set = 1;
while (1) {
afs_int32 cellnum, clen, magic;
- struct cell_name *cn;
char *cellname;
cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
off += cc;
cellname[clen] = '\0';
- if (afs_cellname_lookup_name(cellname) ||
- afs_cellname_lookup_id(cellnum)) {
+ if (afs_cellname_lookup_name(cellname)
+ || afs_cellname_lookup_id(cellnum)) {
afs_osi_Free(cellname, clen + 1);
break;
}
- cn = afs_cellname_new(cellname, cellnum);
+ afs_cellname_new(cellname, cellnum);
afs_osi_Free(cellname, clen + 1);
}
return 0;
}
-int afs_cellname_write()
+/*!
+ * Write in-kernel list of cells to disk.
+ */
+int
+afs_cellname_write(void)
{
struct osi_file *tfile;
struct cell_name *cn;
ObtainWriteLock(&afs_xcell, 693);
afs_cellname_dirty = 0;
off = 0;
- tfile = osi_UFSOpen(afs_cellname_inode);
+ tfile = osi_UFSOpen(&afs_cellname_inode);
if (!tfile) {
ReleaseWriteLock(&afs_xcell);
return EIO;
struct cell_alias *afs_cellalias_head; /* Export for kdump */
static afs_int32 afs_cellalias_index;
-static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
+static int afs_CellOrAliasExists_nl(char *aname); /* Forward declaration */
-static struct cell_alias *afs_FindCellAlias(char *alias)
+/*!
+ * Look up cell alias by alias name.
+ * \param alias
+ * \return Found struct or NULL.
+ */
+static struct cell_alias *
+afs_FindCellAlias(char *alias)
{
struct cell_alias *tc;
return tc;
}
-struct cell_alias *afs_GetCellAlias(int index)
+/*!
+ * Get cell alias by index (starting at 0).
+ * \param index Cell index.
+ * \return Found struct or null.
+ */
+struct cell_alias *
+afs_GetCellAlias(int index)
{
struct cell_alias *tc;
return tc;
}
-void afs_PutCellAlias(struct cell_alias *a)
+
+ /*!
+ * Put back a cell alias returned by Find or Get.
+ * \param a Alias.
+ * \return
+ */
+void
+afs_PutCellAlias(struct cell_alias *a)
{
return;
}
-afs_int32 afs_NewCellAlias(char *alias, char *cell)
+/*!
+ * Create new cell alias entry and update dynroot vnode.
+ * \param alias
+ * \param cell
+ * \return
+ */
+afs_int32
+afs_NewCellAlias(char *alias, char *cell)
{
struct cell_alias *tc;
}
UpgradeSToWLock(&afs_xcell, 682);
- tc = (struct cell_alias *) afs_osi_Alloc(sizeof(struct cell_alias));
+ tc = afs_osi_Alloc(sizeof(struct cell_alias));
+ osi_Assert(tc != NULL);
tc->alias = afs_strdup(alias);
tc->cell = afs_strdup(cell);
tc->next = afs_cellalias_head;
*/
struct afs_q CellLRU; /* Export for kdump */
-static char *afs_thiscell;
-static afs_int32 afs_cellindex;
+static char *afs_thiscell = NULL;
+afs_int32 afs_cellindex; /* Export for kdump */
-static void afs_UpdateCellLRU(struct cell *c)
+/*!
+ * Bump given cell up to the front of the LRU queue.
+ * \param c Cell to set.
+ */
+static void
+afs_UpdateCellLRU(struct cell *c)
{
ObtainWriteLock(&afs_xcell, 100);
QRemove(&c->lruq);
ReleaseWriteLock(&afs_xcell);
}
-static void afs_RefreshCell(struct cell *ac)
+/*!
+ * Look up cell information in AFSDB if timeout expired
+ * \param ac Cell to be refreshed.
+ * \return
+ */
+static void
+afs_RefreshCell(struct cell *ac)
{
if (ac->states & CNoAFSDB)
return;
afs_LookupAFSDB(ac->cellName);
}
-static void *afs_TraverseCells_nl(void *(*cb)(struct cell *, void *), void *arg)
+/*!
+ * Execute a callback for each existing cell, without a lock on afs_xcell.
+ * Iterate on CellLRU, and execute a callback for each cell until given arguments are met.
+ * \see afs_TraverseCells
+ * \param cb Traversal callback for each cell.
+ * \param arg Callback arguments.
+ * \return Found data or NULL.
+ */
+static void *
+afs_TraverseCells_nl(void *(*cb) (struct cell *, void *), void *arg)
{
struct afs_q *cq, *tq;
struct cell *tc;
void *ret = NULL;
for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
+ tc = QTOC(cq);
+
+ /* This is assuming that a NULL return is acceptable. */
+ if (cq) {
+ tq = QNext(cq);
+ } else {
+ return NULL;
+ }
+
ret = cb(tc, arg);
- if (ret) break;
+ if (ret)
+ break;
}
return ret;
}
-void *afs_TraverseCells(void *(*cb)(struct cell *, void *), void *arg)
+/*!
+ * Execute a callback for each existing cell, with a lock on afs_xcell.
+ * \see afs_TraverseCells_nl
+ * \param cb Traversal callback for each cell.
+ * \param arg
+ * \return Found data or NULL.
+ */
+void *
+afs_TraverseCells(void *(*cb) (struct cell *, void *), void *arg)
{
void *ret;
return ret;
}
-static void *afs_choose_cell_by_name(struct cell *cell, void *arg)
+/*!
+ * Useful traversal callback: Match by name.
+ * \param cell
+ * \param arg Cell name (compared with cell->cellName).
+ * \return Returns found cell or NULL.
+ */
+static void *
+afs_choose_cell_by_name(struct cell *cell, void *arg)
+{
+ if (!arg) {
+ /* Safety net */
+ return cell;
+ } else {
+ return strcmp(cell->cellName, (char *)arg) ? NULL : cell;
+ }
+}
+
+/*!
+ * Useful traversal callback: Match by handle.
+ * \param cell
+ * \param arg Cell handle (compared with cell->cellHandle).
+ * \return Returns found cell or NULL.
+ */
+static void *
+afs_choose_cell_by_handle(struct cell *cell, void *arg)
{
- return strcmp(cell->cellName, (char *) arg) ? NULL : cell;
+ if (!arg) {
+ /* Safety net */
+ return cell;
+ } else {
+ return memcmp(cell->cellHandle, (char *)arg, 16) ? NULL : cell;
+ }
}
-static void *afs_choose_cell_by_num(struct cell *cell, void *arg)
+/*!
+ * Useful traversal callback: Match by cell number.
+ * \param cell
+ * \param arg Cell number (compared with cell->cellNum).
+ * \return Returns found cell or NULL.
+ */
+static void *
+afs_choose_cell_by_num(struct cell *cell, void *arg)
{
return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
}
-static void *afs_choose_cell_by_index(struct cell *cell, void *arg)
+/*!
+ * Useful traversal callback: Match by index.
+ * \param cell
+ * \param arg Cell index (compared with cell->cellIndex).
+ * \return Returns found cell or NULL.
+ */
+static void *
+afs_choose_cell_by_index(struct cell *cell, void *arg)
{
return (cell->cellIndex == *((afs_int32 *) arg)) ? cell : NULL;
}
-static struct cell *afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
+/*!
+ * Return a cell with a given name, if it exists. No lock version.
+ * Does not check AFSDB.
+ * \param acellName Cell name.
+ * \param locktype Type of lock to be used (not used).
+ * \return
+ */
+static struct cell *
+afs_FindCellByName_nl(char *acellName, afs_int32 locktype)
{
return afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
}
-static struct cell *afs_FindCellByName(char *acellName, afs_int32 locktype)
+/*!
+ * Return a cell with a given name, if it exists.It uses locks.
+ * Does not check AFSDB.
+ * \param acellName Cell name.
+ * \param locktype Type of lock to be used.
+ * \return
+ */
+static struct cell *
+afs_FindCellByName(char *acellName, afs_int32 locktype)
{
return afs_TraverseCells(&afs_choose_cell_by_name, acellName);
}
-struct cell *afs_GetCellByName(char *acellName, afs_int32 locktype)
+/*!
+ * Same as FindCellByName but tries AFSDB if not found.
+ * \param acellName Cell name.
+ * \param locktype Type of lock to be used.
+ * \return
+ */
+struct cell *
+afs_GetCellByName(char *acellName, afs_int32 locktype)
{
struct cell *tc;
return tc;
}
-struct cell *afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
+/*!
+ * Return a cell with a given cell number.
+ * \param cellnum Cell number.
+ * \param locktype Lock to be used.
+ * \return
+ */
+struct cell *
+afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
{
struct cell *tc;
struct cell_name *cn;
return tc;
}
-struct cell *afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
+/*!
+ * Same as GetCell, but does not try to refresh the data.
+ * \param cellnum Cell number.
+ * \param locktype What lock should be used.
+ * \return
+ */
+struct cell *
+afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
{
struct cell *tc;
return tc;
}
-struct cell *afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
+/*!
+ * Return a cell with a given index number (starting at 0). Update CellLRU as well.
+ * \param index
+ * \param locktype Type of lock used.
+ * \return
+ */
+struct cell *
+afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
{
struct cell *tc;
return tc;
}
-struct cell *afs_GetPrimaryCell(afs_int32 locktype)
+/*!
+ * Return a cell with a given handle..
+ * \param index
+ * \param locktype Type of lock used.
+ * \return
+ */
+struct cell *
+afs_GetCellByHandle(void *handle, afs_int32 locktype)
+{
+ struct cell *tc;
+
+ tc = afs_TraverseCells(&afs_choose_cell_by_handle, handle);
+ if (tc)
+ afs_UpdateCellLRU(tc);
+ return tc;
+}
+
+/*!
+ * Return primary cell, if any.
+ * \param locktype Type of lock used.
+ * \return
+ */
+struct cell *
+afs_GetPrimaryCell(afs_int32 locktype)
{
return afs_GetCellByName(afs_thiscell, locktype);
}
-int afs_IsPrimaryCell(struct cell *cell)
+/*!
+ * Return number of the primary cell.
+ * \return
+ * Cell number, or 0 if primary cell not found
+ */
+afs_int32
+afs_GetPrimaryCellNum(void)
+{
+ struct cell *cell;
+ afs_int32 cellNum = 0;
+ cell = afs_GetPrimaryCell(READ_LOCK);
+ if (cell) {
+ cellNum = cell->cellNum;
+ afs_PutCell(cell, READ_LOCK);
+ }
+ return cellNum;
+}
+
+/*!
+ * Returns true if the given cell is the primary cell.
+ * \param cell
+ * \return
+ */
+int
+afs_IsPrimaryCell(struct cell *cell)
{
- return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
+ /* Simple safe checking */
+ if (!cell) {
+ return 0;
+ } else if (!afs_thiscell) {
+ /* This is simply a safety net to avoid seg faults especially when
+ * using a user-space library. afs_SetPrimaryCell() should be set
+ * prior to this call. */
+ afs_SetPrimaryCell(cell->cellName);
+ return 1;
+ } else {
+ return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
+ }
}
-int afs_IsPrimaryCellNum(afs_int32 cellnum)
+/*!
+ * Returns afs_IsPrimaryCell(afs_GetCell(cellnum)).
+ * \param cellnum
+ * \return
+ */
+int
+afs_IsPrimaryCellNum(afs_int32 cellnum)
{
struct cell *tc;
int primary = 0;
return primary;
}
-afs_int32 afs_SetPrimaryCell(char *acellName)
+/*!
+ * Set the primary cell name to the given cell name.
+ * \param acellName Cell name.
+ * \return 0 for success, < 0 for error.
+ */
+afs_int32
+afs_SetPrimaryCell(char *acellName)
{
ObtainWriteLock(&afs_xcell, 691);
if (afs_thiscell)
return 0;
}
-afs_int32 afs_NewCell(char *acellName, afs_int32 *acellHosts, int aflags,
- char *linkedcname, u_short fsport, u_short vlport, int timeout)
+/*!
+ * Create or update a cell entry.
+ * \param acellName Name of cell.
+ * \param acellHosts Array of hosts that this cell has.
+ * \param aflags Cell flags.
+ * \param linkedcname
+ * \param fsport File server port.
+ * \param vlport Volume server port.
+ * \param timeout Cell timeout value, 0 means static AFSDB entry.
+ * \return
+ */
+afs_int32
+afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
+ char *linkedcname, u_short fsport, u_short vlport, int timeout)
{
- struct cell *tc, *tcl=0;
- afs_int32 i, newc=0, code=0;
+ struct cell *tc, *tcl = 0;
+ afs_int32 i, newc = 0, code = 0;
+ struct md5 m;
AFS_STATCNT(afs_NewCell);
if (tc) {
aflags &= ~CNoSUID;
} else {
- tc = (struct cell *) afs_osi_Alloc(sizeof(struct cell));
- memset((char *) tc, 0, sizeof(*tc));
+ tc = afs_osi_Alloc(sizeof(struct cell));
+ osi_Assert(tc != NULL);
+ memset(tc, 0, sizeof(*tc));
tc->cellName = afs_strdup(acellName);
tc->fsport = AFS_FSPORT;
tc->vlport = AFS_VLPORT;
- RWLOCK_INIT(&tc->lock, "cell lock");
+ MD5_Init(&m);
+ MD5_Update(&m, tc->cellName, strlen(tc->cellName));
+ MD5_Final(tc->cellHandle, &m);
+ AFS_RWLOCK_INIT(&tc->lock, "cell lock");
newc = 1;
- if (afs_thiscell && !strcmp(acellName, afs_thiscell))
- aflags &= ~CNoSUID;
+ aflags |= CNoSUID;
}
ObtainWriteLock(&tc->lock, 688);
* it must get servers from AFSDB.
*/
if (timeout && !tc->timeout && tc->cellHosts[0]) {
- code = EINVAL;
+ code = EEXIST; /* This code is checked for in afs_LookupAFSDB */
goto bad;
}
/* we don't want to keep pinging old vlservers which were down,
* since they don't matter any more. It's easier to do this than
* to remove the server from its various hash tables. */
- for (i=0; i<MAXCELLHOSTS; i++) {
- if (!tc->cellHosts[i]) break;
+ for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
+ if (!tc->cellHosts[i])
+ break;
tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
tc->cellHosts[i]->flags |= SRVR_ISGONE;
}
- if (fsport) tc->fsport = fsport;
- if (vlport) tc->vlport = vlport;
+ if (fsport)
+ tc->fsport = fsport;
+ if (vlport)
+ tc->vlport = vlport;
if (aflags & CLinkedCell) {
if (!linkedcname) {
tc->states |= aflags;
tc->timeout = timeout;
- memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts));
- for (i=0; i<MAXCELLHOSTS; i++) {
+ memset(tc->cellHosts, 0, sizeof(tc->cellHosts));
+ for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
+ /* Get server for each host and link this cell in.*/
struct server *ts;
afs_uint32 temp = acellHosts[i];
- if (!temp) break;
- ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
+ if (!temp)
+ break;
+ ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0, NULL);
ts->cell = tc;
ts->flags &= ~SRVR_ISGONE;
+ /* Set the server as a host of the new cell. */
tc->cellHosts[i] = ts;
afs_PutServer(ts, WRITE_LOCK);
}
- afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
+ afs_SortServers(tc->cellHosts, AFS_MAXCELLHOSTS); /* randomize servers */
+ /* New cell: Build and add to LRU cell queue. */
if (newc) {
struct cell_name *cn;
ReleaseWriteLock(&tc->lock);
ReleaseWriteLock(&afs_xcell);
afs_PutCell(tc, 0);
- afs_DynrootInvalidate();
+ if (!(aflags & CHush))
+ afs_DynrootInvalidate();
return 0;
-bad:
+ bad:
+ ReleaseWriteLock(&tc->lock);
+
if (newc) {
+ /* If we're a new cell, nobody else can see us, so doing this
+ * after lock release is safe */
afs_osi_FreeStr(tc->cellName);
afs_osi_Free(tc, sizeof(struct cell));
}
- ReleaseWriteLock(&tc->lock);
+
ReleaseWriteLock(&afs_xcell);
return code;
}
* afs_CellNumValid: check if a cell number is valid (also set the used flag)
*/
-void afs_CellInit()
+/*!
+ * Perform whatever initialization is necessary.
+ */
+void
+afs_CellInit(void)
{
- RWLOCK_INIT(&afs_xcell, "afs_xcell");
-#ifdef AFS_AFSDB_ENV
- RWLOCK_INIT(&afsdb_req.lock, "afsdb_req.lock");
-#endif
+ static char CellInit_done = 0;
+
+ if (CellInit_done)
+ return;
+
+ CellInit_done = 1;
+
+ AFS_RWLOCK_INIT(&afs_xcell, "afs_xcell");
+ AFS_RWLOCK_INIT(&afsdb_client_lock, "afsdb_client_lock");
+ AFS_RWLOCK_INIT(&afsdb_req_lock, "afsdb_req_lock");
QInit(&CellLRU);
afs_cellindex = 0;
afs_cellalias_index = 0;
}
-void shutdown_cell()
+/*!
+ * Called on shutdown, should deallocate memory, etc.
+ */
+void
+shutdown_cell(void)
{
struct afs_q *cq, *tq;
struct cell *tc;
- RWLOCK_INIT(&afs_xcell, "afs_xcell");
+#ifdef AFS_CACHE_VNODE_PATH
+ if (cacheDiskType != AFS_FCACHE_TYPE_MEM) {
+ afs_osi_FreeStr(afs_cellname_inode.ufs);
+ }
+#endif
+ AFS_RWLOCK_INIT(&afs_xcell, "afs_xcell");
for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
- if (tc->cellName) afs_osi_FreeStr(tc->cellName);
+ tc = QTOC(cq);
+ tq = QNext(cq);
+ if (tc->cellName)
+ afs_osi_FreeStr(tc->cellName);
afs_osi_Free(tc, sizeof(struct cell));
}
QInit(&CellLRU);
+
+{
+ struct cell_name *cn = afs_cellname_head;
+
+ while (cn) {
+ struct cell_name *next = cn->next;
+
+ afs_osi_FreeStr(cn->cellname);
+ afs_osi_Free(cn, sizeof(struct cell_name));
+ cn = next;
+ }
+}
}
-void afs_RemoveCellEntry(struct server *srvp)
+/*!
+ * Remove a server from a cell's server list.
+ * \param srvp Server to be removed.
+ * \return
+ */
+void
+afs_RemoveCellEntry(struct server *srvp)
{
struct cell *tc;
afs_int32 j, k;
tc = srvp->cell;
- if (!tc) return;
+ if (!tc)
+ return;
/* Remove the server structure from the cell list - if there */
ObtainWriteLock(&tc->lock, 200);
- for (j=k=0; j<MAXCELLHOSTS; j++) {
- if (!tc->cellHosts[j]) break;
+ for (j = k = 0; j < AFS_MAXCELLHOSTS; j++) {
+ if (!tc->cellHosts[j])
+ break;
if (tc->cellHosts[j] != srvp) {
tc->cellHosts[k++] = tc->cellHosts[j];
}
if (k == 0) {
/* What do we do if we remove the last one? */
}
- for (; k<MAXCELLHOSTS; k++) {
+ for (; k < AFS_MAXCELLHOSTS; k++) {
tc->cellHosts[k] = 0;
}
ReleaseWriteLock(&tc->lock);
}
-static int afs_CellOrAliasExists_nl(char *aname)
+/*!
+ * Check if the given name exists as a cell or alias. Does not lock afs_xcell.
+ * \param aname
+ * \return
+ */
+static int
+afs_CellOrAliasExists_nl(char *aname)
{
struct cell *c;
struct cell_alias *ca;
return 0;
}
-int afs_CellOrAliasExists(char *aname)
+/*!
+ * Check if the given name exists as a cell or alias. Locks afs_xcell.
+ * \param aname
+ * \return
+ */
+int
+afs_CellOrAliasExists(char *aname)
{
int ret;
return ret;
}
-int afs_CellNumValid(afs_int32 cellnum)
+/*!
+ * Check if a cell number is valid (also set the used flag).
+ * \param cellnum
+ * \return 1 - true, 0 - false
+ */
+int
+afs_CellNumValid(afs_int32 cellnum)
{
struct cell_name *cn;