{
struct VenusFid vfid;
struct vrequest treq;
- extern struct cell *afs_GetCellByIndex();
register struct cell *tcell;
register afs_int32 code = 0;
afs_int32 ret;
afid2 = (afs_fid2_t*)fidp;
if (afid2->af_len == sizeof(afs_fid2_t) - sizeof(afid2->af_len)) {
/* It's a checkpoint restart fid. */
- tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK, 0 /* !refresh */);
+ tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK);
if (!tcell) {
code = ENOENT;
goto out;
- }
- vfid.Cell = tcell->cell;
- afs_PutCell(tcell, WRITE_LOCK);
+ }
+ vfid.Cell = tcell->cellNum;
+ afs_PutCell(tcell, READ_LOCK);
vfid.Fid.Volume = afid2->af_volid;
vfid.Fid.Vnode = afid2->af_vno;
vfid.Fid.Unique = afid2->af_uniq;
}
if (!tcell) return ENODEV;
- mtptCell = tcell->cell; /* The cell for the mountpoint */
+ mtptCell = tcell->cellNum; /* The cell for the mountpoint */
if (tcell->lcellp) {
- hac = 1; /* has associated cell */
- assocCell = tcell->lcellp->cell; /* The associated cell */
+ hac = 1; /* has associated cell */
+ assocCell = tcell->lcellp->cellNum; /* The associated cell */
}
afs_PutCell(tcell, READ_LOCK);
*/
void afs_InitFakeStat(struct afs_fakestat_state *state)
{
+ if (!afs_fakestat_enable)
+ return;
+
state->valid = 1;
state->did_eval = 0;
state->need_release = 0;
struct volume *tvolp = NULL;
int code = 0;
+ if (!afs_fakestat_enable)
+ return 0;
+
osi_Assert(state->valid == 1);
osi_Assert(state->did_eval == 0);
state->did_eval = 1;
- if (!afs_fakestat_enable)
- return 0;
+
tvc = *avcp;
if (tvc->mvstat != 1)
return 0;
*/
void afs_PutFakeStat(struct afs_fakestat_state *state)
{
+ if (!afs_fakestat_enable)
+ return;
+
osi_Assert(state->valid == 1);
if (state->need_release)
afs_PutVCache(state->root_vp);
afs_PutDCache(tdc);
if (code == ENOENT && afs_IsDynroot(adp) && dynrootRetry) {
- struct cell *tcell;
-
ReleaseReadLock(&adp->lock);
dynrootRetry = 0;
- if (*tname == '.')
- tcell = afs_GetCellByName(tname + 1, READ_LOCK);
+ if (tname[0] == '.')
+ afs_LookupAFSDB(tname + 1);
else
- tcell = afs_GetCellByName(tname, READ_LOCK);
- if (tcell) {
- afs_PutCell(tcell, READ_LOCK);
- afs_RefreshDynroot();
- if (tname != aname && tname) osi_FreeLargeSpace(tname);
- goto redo;
- }
+ afs_LookupAFSDB(tname);
+ if (tname && tname != aname) osi_FreeLargeSpace(tname);
+ goto redo;
} else {
ReleaseReadLock(&adp->lock);
}
struct AFSFid fid;
};
-
-#define LOCALCELL 1 /* local cell's number is always 1 */
+/* cellinfo file magic number */
+#define AFS_CELLINFO_MAGIC 0xf32817cd
/* cell flags */
-#define CPrimary 1 /* on if this is the primary cell */
-#define CNoSUID 2 /* 1 if no suid progs can run from this cell */
-#define CHasVolRef 16 /* Volumes were referenced in this cell*/
-#define CLinkedCell 32
-#define CAlias 64 /* This cell entry is an alias */
+#define CNoSUID 0x02 /* disable suid bit for this cell */
+#define CLinkedCell4 0x04 /* reserved for ADDCELL2 pioctl */
+#define CNoAFSDB 0x08 /* never bother trying AFSDB */
+#define CHasVolRef 0x10 /* volumes were referenced */
+#define CLinkedCell 0x20 /* has a linked cell in lcellp */
struct cell {
- struct afs_q lruq; /* lru q next and prev */
- afs_int32 cell; /* unique id assigned by venus */
+ struct afs_q lruq; /* lru q next and prev */
char *cellName; /* char string name of cell */
- struct server *cellHosts[MAXCELLHOSTS]; /* volume *location* hosts for this cell */
+ afs_int32 cellIndex; /* sequence number */
+ afs_int32 cellNum; /* semi-permanent cell number */
+ struct server *cellHosts[MAXCELLHOSTS]; /* volume *location* hosts */
struct cell *lcellp; /* Associated linked cell */
u_short fsport; /* file server port */
u_short vlport; /* volume server port */
short states; /* state flags */
- short cellIndex; /* relative index number per cell */
- short realcellIndex; /* as above but ignoring aliases */
time_t timeout; /* data expire time, if non-zero */
- char *realName; /* who this cell is an alias for */
+ struct cell_name *cnamep; /* pointer to our cell_name */
+ afs_rwlock_t lock; /* protects cell data */
+};
+
+struct cell_name {
+ struct cell_name *next;
+ afs_int32 cellnum;
+ char *cellname;
+ char used;
+};
+
+struct cell_alias {
+ struct cell_alias *next;
+ afs_int32 index;
+ char *alias;
+ char *cell;
};
#define afs_PutCell(cellp, locktype)
do {
VSleep(2); /* Better safe than sorry. */
tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
- tcell->cell, &treq, SHARED_LOCK);
+ tcell->cellNum, &treq, SHARED_LOCK);
if (tconn) {
if (tconn->srvr->server->flags & SNO_LHOSTS) {
type = 0;
if (aerrP)
(aerrP->err_Network)++;
if (hm_retry_int && !(areq->flags & O_NONBLOCK) && /* "hard" mount */
- ((afid && afid->Cell == LOCALCELL) ||
- (cellp && cellp->cell == LOCALCELL))) {
+ ((afid && afs_IsPrimaryCellNum(afid->Cell)) ||
+ (cellp && afs_IsPrimaryCell(cellp)))) {
if (!afid) {
afs_warnuser("afs: hard-mount waiting for a vlserver to return to service\n");
VSleep(hm_retry_int);
if (aerrP)
(aerrP->err_Protection)++;
- tu = afs_FindUser(areq->uid, tsp->cell->cell, READ_LOCK);
+ tu = afs_FindUser(areq->uid, tsp->cell->cellNum, READ_LOCK);
if (tu) {
if ((acode == VICETOKENDEAD) || (acode == RXKADEXPIRED))
afs_warnuser("afs: Tokens for user of AFS id %d for cell %s have expired\n",
static int afs_Go_Done = 0;
extern struct interfaceAddr afs_cb_interface;
static int afs_RX_Running = 0;
+static int afs_InitSetup_done = 0;
static int
Afscall_icl(long opcode, long p1, long p2, long p3, long p4, long *retval);
extern void afs_InitStats();
int code;
+ if (afs_InitSetup_done)
+ return;
+
#ifndef AFS_NOSTATS
/*
* Set up all the AFS statistics variables. This should be done
/* resource init creates the services */
afs_ResourceInit(preallocs);
+ afs_InitSetup_done = 1;
+ afs_osi_Wakeup(&afs_InitSetup_done);
+
return code;
}
long parm, parm2, parm3, parm4, parm5, parm6;
{
afs_int32 code = 0;
+#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+ size_t bufferSize;
+#else /* AFS_SGI61_ENV */
+ u_int bufferSize;
+#endif /* AFS_SGI61_ENV */
AFS_STATCNT(afs_syscall_call);
#ifdef AFS_SUN5_ENV
#endif
}
#endif
- else if (parm == AFSOP_START_AFS) {
- /* afs daemon */
+ else if (parm == AFSOP_BASIC_INIT) {
afs_int32 temp;
- if (AFS_Running) goto out;
- AFS_Running = 1;
- while (afs_initState < AFSOP_START_AFS)
- afs_osi_Sleep(&afs_initState);
+ while (!afs_InitSetup_done)
+ afs_osi_Sleep(&afs_InitSetup_done);
#if defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
temp = AFS_MINBUFFERS; /* Should fix this soon */
#else
- temp = ((afs_bufferpages * NBPG)>>11); /* number of 2k buffers we could get from all of the buffer space */
+ /* number of 2k buffers we could get from all of the buffer space */
+ temp = ((afs_bufferpages * NBPG)>>11);
temp = temp>>2; /* don't take more than 25% (our magic parameter) */
- if (temp < AFS_MINBUFFERS) temp = AFS_MINBUFFERS; /* although we really should have this many */
+ if (temp < AFS_MINBUFFERS)
+ temp = AFS_MINBUFFERS; /* though we really should have this many */
#endif
DInit(temp);
+ afs_rootFid.Fid.Volume = 0;
+ code = 0;
+ }
+ else if (parm == AFSOP_START_AFS) {
+ /* afs daemon */
+ if (AFS_Running) goto out;
+ AFS_Running = 1;
+ while (afs_initState < AFSOP_START_AFS)
+ afs_osi_Sleep(&afs_initState);
+
afs_initState = AFSOP_START_BKG;
afs_osi_Wakeup(&afs_initState);
afs_osi_Invisible();
home cell flag (0x1 bit) and the nosuid flag (0x2 bit) */
struct afsop_cell tcell;
- while (afs_initState < AFSOP_START_BKG) afs_osi_Sleep(&afs_initState);
AFS_COPYIN((char *)parm2, (char *)tcell.hosts, sizeof(tcell.hosts), code);
if (!code) {
if (parm4 > sizeof(tcell.cellName))
AFS_COPYIN((char *)parm3, tcell.cellName, parm4, code);
if (!code)
afs_NewCell(tcell.cellName, tcell.hosts, parm5,
- 0, 0, 0, 0, 0);
+ NULL, 0, 0, 0);
}
}
} else if (parm == AFSOP_ADDCELL2) {
struct afsop_cell tcell;
char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ), *lcnamep = 0;
char *tbuffer1 = osi_AllocSmallSpace(AFS_SMALLOCSIZ), *cnamep = 0;
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- size_t bufferSize;
-#else /* AFS_SGI61_ENV */
- u_int bufferSize;
-#endif /* AFS_SGI61_ENV */
int cflags = parm4;
/* wait for basic init */
}
}
if (!code)
- afs_NewCell(tbuffer1, tcell.hosts, cflags,
- lcnamep, 0, 0, 0, 0);
+ code = afs_NewCell(tbuffer1, tcell.hosts, cflags,
+ lcnamep, 0, 0, 0);
}
}
osi_FreeSmallSpace(tbuffer);
* parm2 is the alias name
* parm3 is the real cell name
*/
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- size_t bufferSize;
-#else /* AFS_SGI61_ENV */
- u_int bufferSize;
-#endif /* AFS_SGI61_ENV */
char *aliasName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
char *cellName = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
AFS_COPYINSTR((char *)parm2, aliasName, AFS_SMALLOCSIZ, &bufferSize, code);
if (!code) AFS_COPYINSTR((char *)parm3, cellName, AFS_SMALLOCSIZ, &bufferSize, code);
- if (!code) afs_NewCell(aliasName, /* new entry name */
- 0, /* host list */
- CAlias, /* flags */
- NULL, /* linked cell */
- 0, 0, /* fs & vl ports */
- 0, /* timeout */
- cellName); /* real cell name */
-
+ if (!code) afs_NewCellAlias(aliasName, cellName);
osi_FreeSmallSpace(aliasName);
osi_FreeSmallSpace(cellName);
}
+ else if (parm == AFSOP_SET_THISCELL) {
+ /*
+ * Call arguments:
+ * parm2 is the primary cell name
+ */
+ char *cell = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
+
+ AFS_COPYINSTR((char *) parm2, cell, AFS_SMALLOCSIZ, &bufferSize, code);
+ if (!code)
+ afs_SetPrimaryCell(cell);
+ osi_FreeSmallSpace(cell);
+ }
else if (parm == AFSOP_CACHEINIT) {
struct afs_cacheParams cparms;
if (afs_CacheInit_Done) goto out;
- /* wait for basic init */
- while (afs_initState < AFSOP_START_BKG) afs_osi_Sleep(&afs_initState);
AFS_COPYIN((char *)parm2, (caddr_t) &cparms, sizeof(cparms), code);
if (code) {
#if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined (AFS_SGI64_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
code = afs_InitCacheFile(NULL, ainode);
}
else if (parm == AFSOP_ROOTVOLUME) {
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- size_t bufferSize;
-#else /* AFS_SGI61_ENV */
- u_int bufferSize;
-#endif /* AFS_SGI61_ENV */
-
/* wait for basic init */
while (afs_initState < AFSOP_START_BKG) afs_osi_Sleep(&afs_initState);
}
else code = 0;
}
- else if (parm == AFSOP_CACHEFILE || parm == AFSOP_CACHEINFO ||
- parm == AFSOP_VOLUMEINFO || parm == AFSOP_AFSLOG) {
+ else if (parm == AFSOP_CACHEFILE ||
+ parm == AFSOP_CACHEINFO ||
+ parm == AFSOP_VOLUMEINFO ||
+ parm == AFSOP_AFSLOG ||
+ parm == AFSOP_CELLINFO) {
char *tbuffer = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
-#if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
- size_t bufferSize;
-#else /* AFS_SGI61_ENV */
- u_int bufferSize;
-#endif /* AFS_SGI61_ENV */
- /* wait for basic init */
- while (afs_initState < AFSOP_START_BKG) afs_osi_Sleep(&afs_initState);
code = 0;
- AFS_COPYINSTR((char *)parm2, tbuffer, AFS_SMALLOCSIZ, &bufferSize, code);
+ AFS_COPYINSTR((char *) parm2, tbuffer, AFS_SMALLOCSIZ,
+ &bufferSize, code);
if (code) {
osi_FreeSmallSpace(tbuffer);
goto out;
}
if (!code) {
- tbuffer[AFS_SMALLOCSIZ-1] = 0; /* null-terminate the name */
- /* we now have the cache dir copied in. Call the cache init routines */
- if (parm == AFSOP_CACHEFILE) code = afs_InitCacheFile(tbuffer, 0);
- else if (parm == AFSOP_CACHEINFO) code = afs_InitCacheInfo(tbuffer);
- else if (parm == AFSOP_VOLUMEINFO) code = afs_InitVolumeInfo(tbuffer);
+ tbuffer[AFS_SMALLOCSIZ-1] = '\0'; /* null-terminate the name */
+ /* We have the cache dir copied in. Call the cache init routine */
+ if (parm == AFSOP_CACHEFILE)
+ code = afs_InitCacheFile(tbuffer, 0);
+ else if (parm == AFSOP_CACHEINFO)
+ code = afs_InitCacheInfo(tbuffer);
+ else if (parm == AFSOP_VOLUMEINFO)
+ code = afs_InitVolumeInfo(tbuffer);
+ else if (parm == AFSOP_CELLINFO)
+ code = afs_InitCellInfo(tbuffer);
}
osi_FreeSmallSpace(tbuffer);
}
AFS_COPYIN((afs_int32 *)parm2, cellname, cellLen, code);
AFS_COPYIN((afs_int32 *)parm3, kmsg, kmsgLen, code);
if (!code) {
- code = afs_AfsdbHandler(cellname, cellLen, kmsg);
+ code = afs_AFSDBHandler(cellname, cellLen, kmsg);
if (*cellname == 1) *cellname = 0;
if (code == -2) { /* Shutting down? */
*cellname = 1;
}
#ifdef AFS_AFSDB_ENV
afs_warn("AFSDB... ");
- afs_StopAfsdb();
+ afs_StopAFSDB();
while (afs_termState == AFSOP_STOP_AFSDB)
afs_osi_Sleep(&afs_termState);
#endif
RX_AFS_GLOCK();
AFS_STATCNT(SRXAFSCB_GetCellServDB);
- tcell = afs_GetCellByIndex(a_index, READ_LOCK, 0);
+ tcell = afs_GetCellByIndex(a_index, READ_LOCK);
if (!tcell) {
i = 0;
{
int plen;
struct cell *tcell;
- struct afs_q *cq, *tq;
char *t_name, *p_name = NULL;
RX_AFS_GLOCK();
/* Search the list for the primary cell. Cell number 1 is only
* the primary cell is when no other cell is explicitly marked as
* the primary cell. */
- ObtainReadLock(&afs_xcell);
-
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tq = QNext(cq);
- tcell = QTOC(cq);
- if (tcell->states & CPrimary) {
- p_name = tcell->cellName;
- break;
- }
- if (tcell->cell == 1) {
- p_name = tcell->cellName;
- }
- }
-
+ tcell = afs_GetPrimaryCell(READ_LOCK);
+ if (tcell)
+ p_name = tcell->cellName;
if (p_name)
plen = strlen(p_name);
else
plen = 0;
t_name = (char *)afs_osi_Alloc(plen+1);
if (t_name == NULL) {
- ReleaseReadLock(&afs_xcell);
+ if (tcell) afs_PutCell(tcell, READ_LOCK);
RX_AFS_GUNLOCK();
return ENOMEM;
}
if (p_name)
memcpy(t_name, p_name, plen);
- ReleaseReadLock(&afs_xcell);
-
RX_AFS_GUNLOCK();
*a_name = t_name;
+ if (tcell) afs_PutCell(tcell, READ_LOCK);
return 0;
}
{
return ENOSYS;
}
+
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_GetCellByNum
+ *
+ * Description:
+ * Routine to get information about a cell specified by its
+ * cell number (returned by GetCE/GetCE64).
+ *
+ * Arguments:
+ * a_call : Ptr to Rx call on which this request came in.
+ * a_cellnum : Input cell number
+ * a_name : Output cell name (one zero byte when no such cell).
+ * a_hosts : Output cell database servers in host byte order.
+ *
+ * Returns:
+ * 0 on success
+ *
+ * Environment:
+ * Nothing interesting.
+ *
+ * Side Effects:
+ * As advertised.
+ *------------------------------------------------------------------------*/
+
+int SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
+ char **a_name, serverList *a_hosts)
+{
+ afs_int32 i, sn;
+ struct cell *tcell;
+
+ RX_AFS_GLOCK();
+ AFS_STATCNT(SRXAFSCB_GetCellByNum);
+
+ a_hosts->serverList_val = 0;
+ a_hosts->serverList_len = 0;
+
+ tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
+ if (!tcell) {
+ *a_name = afs_strdup("");
+ RX_AFS_GUNLOCK();
+ return 0;
+ }
+
+ ObtainReadLock(&tcell->lock);
+ *a_name = afs_strdup(tcell->cellName);
+
+ for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++)
+ ;
+ a_hosts->serverList_len = sn;
+ a_hosts->serverList_val = (afs_int32 *) afs_osi_Alloc(sn*sizeof(afs_int32));
+
+ for (i = 0; i < sn; i++)
+ a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
+ ReleaseReadLock(&tcell->lock);
+ afs_PutCell(tcell, READ_LOCK);
+
+ RX_AFS_GUNLOCK();
+ return 0;
+}
+
#include "../afs/stds.h"
#include "../afs/sysincludes.h" /* Standard vendor system headers */
-
-#if !defined(UKERNEL)
-#include <net/if.h>
-#include <netinet/in.h>
-
-#ifdef AFS_SGI62_ENV
-#include "../h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* ! ASF_HPUX110_ENV */
-#endif /* !defined(UKERNEL) */
-
#include "../afs/afsincludes.h" /* Afs-based standard headers */
#include "../afs/afs_stats.h" /* afs statistics */
-
-#if defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
-#include <netinet/ip6.h>
-#endif
-#include <inet/ip.h>
-#endif
-
-/* Exported variables */
-afs_rwlock_t afs_xcell; /* allocation lock for cells */
-struct afs_q CellLRU;
-afs_int32 afs_cellindex=0;
-afs_int32 afs_realcellindex=0;
-afs_uint32 afs_nextCellNum = 0x100;
+#include "../afs/afs_osi.h"
/* Local variables. */
-struct cell *afs_rootcell = 0;
-
-/* Handler waiting for request from client */
-static int afs_AfsdbHandlerWait;
-/* Client waiting for handler to become available or finish request */
-static int afs_AfsdbLookupWait;
-
-/* Set to 1 when we've seen the userspace AFSDB process at least once */
-char afs_AfsdbHandlerPresent = 0;
-/* Set to 1 when there is a client interacting with the AFSDB handler.
- * Protects the in and out variables below. Protected by GLOCK. */
-char afs_AfsdbHandlerInuse = 0;
-/* Set to 1 when AFSDB has been shut down */
-char afs_AfsdbHandlerShutdown = 0;
-
-/* Input to handler from the client: cell name to look up */
-char *afs_AfsdbHandler_CellName;
-/* Outputs from handler to client: cell hosts, TTL, and real cell name */
-afs_int32 *afs_AfsdbHandler_CellHosts;
-int *afs_AfsdbHandler_Timeout;
-char **afs_AfsdbHandler_RealName;
-
-/* Client sets ReqPending to 1 whenever it queues a request for it */
-char afs_AfsdbHandler_ReqPending = 0;
-/* Handler sets Completed to 1 when it completes the client request */
-char afs_AfsdbHandler_Completed = 0;
+afs_rwlock_t afs_xcell; /* Export for cmdebug peeking at locks */
+
+/*
+ * AFSDB implementation:
+ *
+ * afs_StopAFSDB: terminate the AFSDB handler, used on shutdown
+ * afs_AFSDBHandler: entry point for user-space AFSDB request handler
+ * afs_GetCellHostsAFSDB: query the AFSDB handler and wait for response
+ * afs_LookupAFSDB: look up AFSDB for given cell name and create locally
+ */
#ifdef AFS_AFSDB_ENV
-void afs_StopAfsdb(void)
+static afs_rwlock_t afsdb_client_lock; /* Serializes client requests */
+static char afsdb_handler_running; /* Protected by GLOCK */
+static char afsdb_handler_shutdown; /* Protected by GLOCK */
+
+static struct {
+ afs_rwlock_t lock;
+ char pending;
+ char complete;
+ char *cellname;
+ afs_int32 *cellhosts;
+ int *timeout;
+ char **realname;
+} afsdb_req;
+
+void afs_StopAFSDB()
{
- if (afs_AfsdbHandlerPresent) {
- afs_osi_Wakeup(&afs_AfsdbHandlerWait);
+ if (afsdb_handler_running) {
+ afs_osi_Wakeup(&afsdb_req);
} else {
- afs_AfsdbHandlerShutdown = 1;
+ afsdb_handler_shutdown = 1;
afs_termState = AFSOP_STOP_RXEVENT;
}
}
-int afs_AfsdbHandler(char *acellName, int acellNameLen, afs_int32 *kernelMsg)
+int afs_AFSDBHandler(char *acellName, int acellNameLen, afs_int32 *kernelMsg)
{
- /* afs_syscall_call() has already grabbed the global lock */
-
- if (afs_AfsdbHandlerShutdown) return -2;
- afs_AfsdbHandlerPresent = 1;
+ if (afsdb_handler_shutdown) return -2;
+ afsdb_handler_running = 1;
- if (afs_AfsdbHandler_ReqPending) {
+ ObtainSharedLock(&afsdb_req.lock, 683);
+ if (afsdb_req.pending) {
int i, hostCount;
+ UpgradeSToWLock(&afsdb_req.lock, 684);
hostCount = kernelMsg[0];
- *afs_AfsdbHandler_Timeout = kernelMsg[1];
- if (*afs_AfsdbHandler_Timeout) *afs_AfsdbHandler_Timeout += osi_Time();
-
- *afs_AfsdbHandler_RealName = afs_osi_Alloc(strlen(acellName) + 1);
- strcpy(*afs_AfsdbHandler_RealName, acellName);
+ *afsdb_req.timeout = kernelMsg[1];
+ if (*afsdb_req.timeout) *afsdb_req.timeout += osi_Time();
+ *afsdb_req.realname = afs_strdup(acellName);
for (i=0; i<MAXCELLHOSTS; i++) {
if (i >= hostCount)
- afs_AfsdbHandler_CellHosts[i] = 0;
+ afsdb_req.cellhosts[i] = 0;
else
- afs_AfsdbHandler_CellHosts[i] = kernelMsg[2+i];
+ afsdb_req.cellhosts[i] = kernelMsg[2+i];
}
/* Request completed, wake up the relevant thread */
- afs_AfsdbHandler_ReqPending = 0;
- afs_AfsdbHandler_Completed = 1;
- afs_osi_Wakeup(&afs_AfsdbLookupWait);
+ afsdb_req.pending = 0;
+ afsdb_req.complete = 1;
+ afs_osi_Wakeup(&afsdb_req);
+ ConvertWToSLock(&afsdb_req.lock);
}
+ ConvertSToRLock(&afsdb_req.lock);
/* Wait for a request */
- while (afs_AfsdbHandler_ReqPending == 0 && afs_termState != AFSOP_STOP_AFSDB)
- afs_osi_Sleep(&afs_AfsdbHandlerWait);
+ while (afsdb_req.pending == 0 && afs_termState != AFSOP_STOP_AFSDB) {
+ ReleaseReadLock(&afsdb_req.lock);
+ afs_osi_Sleep(&afsdb_req);
+ ObtainReadLock(&afsdb_req.lock);
+ }
/* Check if we're shutting down */
if (afs_termState == AFSOP_STOP_AFSDB) {
+ ReleaseReadLock(&afsdb_req.lock);
+
/* Inform anyone waiting for us that we're going away */
- afs_AfsdbHandlerShutdown = 1;
- afs_AfsdbHandlerPresent = 0;
- afs_osi_Wakeup(&afs_AfsdbLookupWait);
+ afsdb_handler_shutdown = 1;
+ afsdb_handler_running = 0;
+ afs_osi_Wakeup(&afsdb_req);
afs_termState = AFSOP_STOP_RXEVENT;
afs_osi_Wakeup(&afs_termState);
return -2;
}
- /* Copy the requested cell name into the request buffer */
- strncpy(acellName, afs_AfsdbHandler_CellName, acellNameLen);
-
/* Return the lookup request to userspace */
+ strncpy(acellName, afsdb_req.cellname, acellNameLen);
+ ReleaseReadLock(&afsdb_req.lock);
return 0;
}
-#endif
-
-int afs_GetCellHostsFromDns(char *acellName, afs_int32 *acellHosts,
+static int afs_GetCellHostsAFSDB(char *acellName, afs_int32 *acellHosts,
int *timeout, char **realName)
{
-#ifdef AFS_AFSDB_ENV
- char grab_glock = 0;
+ AFS_ASSERT_GLOCK();
+ if (!afsdb_handler_running) return ENOENT;
- if (!afs_AfsdbHandlerPresent) return ENOENT;
+ ObtainWriteLock(&afsdb_client_lock, 685);
+ ObtainWriteLock(&afsdb_req.lock, 686);
- /* Initialize host list to empty in case the handler is gone */
*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);
+
+ while (afsdb_handler_running && !afsdb_req.complete) {
+ ReleaseReadLock(&afsdb_req.lock);
+ afs_osi_Sleep(&afsdb_req);
+ ObtainReadLock(&afsdb_req.lock);
+ };
+ ReleaseReadLock(&afsdb_req.lock);
+ ReleaseWriteLock(&afsdb_client_lock);
+
+ if (*acellHosts)
+ return 0;
+ else
+ return ENOENT;
+}
+#endif
- if (!ISAFS_GLOCK()) {
- grab_glock = 1;
- AFS_GLOCK();
- }
+void afs_LookupAFSDB(char *acellName)
+{
+#ifdef AFS_AFSDB_ENV
+ afs_int32 cellHosts[MAXCELLHOSTS];
+ char *realName = NULL;
+ struct cell *tc;
+ 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;
- /* Wait until the AFSDB handler is available, and grab it */
- while (afs_AfsdbHandlerInuse)
- afs_osi_Sleep(&afs_AfsdbLookupWait);
- afs_AfsdbHandlerInuse = 1;
+ /* If we found an alias, create it */
+ if (afs_strcasecmp(acellName, realName))
+ afs_NewCellAlias(acellName, realName);
- /* Set up parameters for the handler */
- afs_AfsdbHandler_CellName = acellName;
- afs_AfsdbHandler_CellHosts = acellHosts;
- afs_AfsdbHandler_Timeout = timeout;
- afs_AfsdbHandler_RealName = realName;
+done:
+ if (realName)
+ afs_osi_FreeStr(realName);
+#endif
+}
- /* Wake up the AFSDB handler */
- afs_AfsdbHandler_Completed = 0;
- afs_AfsdbHandler_ReqPending = 1;
- afs_osi_Wakeup(&afs_AfsdbHandlerWait);
+/*
+ * Cell name-to-ID mapping
+ *
+ * afs_cellname_new: create a new cell name, optional cell number
+ * afs_cellname_lookup_id: look up a cell name
+ * afs_cellname_lookup_name: look up a cell number
+ * afs_cellname_ref: note that this cell name was referenced somewhere
+ * afs_cellname_init: load the list of cells from given inode
+ * afs_cellname_write: write in-kernel list of cells to disk
+ */
+
+struct cell_name *afs_cellname_head; /* Export for kdump */
+static ino_t afs_cellname_inode;
+static int afs_cellname_inode_set;
+static int afs_cellname_dirty;
+static afs_int32 afs_cellnum_next;
- /* Wait for the handler to get back to us with the reply */
- while (afs_AfsdbHandlerPresent && !afs_AfsdbHandler_Completed)
- afs_osi_Sleep(&afs_AfsdbLookupWait);
+static struct cell_name *afs_cellname_new(char *name, afs_int32 cellnum)
+{
+ struct cell_name *cn;
- /* Release the AFSDB handler and wake up others waiting for it */
- afs_AfsdbHandlerInuse = 0;
- afs_osi_Wakeup(&afs_AfsdbLookupWait);
+ if (cellnum == 0)
+ cellnum = afs_cellnum_next;
- if (grab_glock) AFS_GUNLOCK();
+ cn = (struct cell_name *) afs_osi_Alloc(sizeof(*cn));
+ cn->next = afs_cellname_head;
+ cn->cellnum = cellnum;
+ cn->cellname = afs_strdup(name);
+ cn->used = 0;
+ afs_cellname_head = cn;
- if (*acellHosts) return 0;
- return ENOENT;
-#else
- return ENOENT;
-#endif
+ if (cellnum >= afs_cellnum_next)
+ afs_cellnum_next = cellnum + 1;
+
+ return cn;
}
+static struct cell_name *afs_cellname_lookup_id(afs_int32 cellnum)
+{
+ struct cell_name *cn;
+
+ for (cn = afs_cellname_head; cn; cn = cn->next)
+ if (cn->cellnum == cellnum)
+ return cn;
-void afs_RefreshCell(register struct cell *ac)
+ return NULL;
+}
+
+static struct cell_name *afs_cellname_lookup_name(char *name)
{
- afs_int32 cellHosts[MAXCELLHOSTS];
- char *realName = NULL;
- struct cell *tc;
- int timeout;
-
- if (ac->cellHosts[0]) /* If we already have some servers.. */
- if (!ac->timeout || ac->timeout > osi_Time())
- /* Don't refresh if not expired */
- return;
-
- if (afs_GetCellHostsFromDns(ac->cellName, cellHosts, &timeout, &realName))
- /* In case of lookup failure, keep old data */
- goto done;
-
- /* Refresh the DB servers for the real cell; other values stay the same. */
- afs_NewCell(realName, cellHosts, 0, NULL, 0, 0, timeout, NULL);
-
- /* If this is an alias, update the alias entry too */
- if (afs_strcasecmp(ac->cellName, realName)) {
- /*
- * Look up the entry we just updated, to compensate for
- * uppercase-vs-lowercase lossage with DNS.
- */
- tc = afs_FindCellByName(realName, READ_LOCK);
-
- if (tc) {
- afs_NewCell(ac->cellName, 0, CAlias, NULL, 0, 0,
- timeout, tc->cellName);
- afs_PutCell(tc, READ_LOCK);
- }
- }
+ struct cell_name *cn;
-done:
- if (realName)
- afs_osi_Free(realName, strlen(realName) + 1);
+ for (cn = afs_cellname_head; cn; cn = cn->next)
+ if (strcmp(cn->cellname, name) == 0)
+ return cn;
+
+ return NULL;
}
+static void afs_cellname_ref(struct cell_name *cn)
+{
+ if (!cn->used) {
+ cn->used = 1;
+ afs_cellname_dirty = 1;
+ }
+}
-struct cell *afs_GetCellByName_Dns(register char *acellName, afs_int32 locktype)
+int afs_cellname_init(ino_t inode, int lookupcode)
{
- afs_int32 cellHosts[MAXCELLHOSTS];
- char *realName = NULL;
- struct cell *tc;
- int timeout;
+ struct osi_file *tfile;
+ int cc, off = 0;
- if (afs_GetCellHostsFromDns(acellName, cellHosts, &timeout, &realName))
- goto bad;
- if (afs_NewCell(realName, cellHosts, CNoSUID, NULL, 0, 0,
- timeout, NULL))
- goto bad;
+ ObtainWriteLock(&afs_xcell, 692);
- /* If this is an alias, create an entry for it too */
- if (afs_strcasecmp(acellName, realName)) {
- /*
- * Look up the entry we just updated, to compensate for
- * uppercase-vs-lowercase lossage with DNS.
- */
- tc = afs_FindCellByName(realName, READ_LOCK);
- if (!tc)
- goto bad;
+ afs_cellnum_next = 1;
+ afs_cellname_dirty = 0;
- if (afs_NewCell(acellName, 0, CAlias, NULL, 0, 0,
- timeout, tc->cellName)) {
- afs_PutCell(tc, READ_LOCK);
- goto bad;
+ if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
+ ReleaseWriteLock(&afs_xcell);
+ return 0;
+ }
+ if (lookupcode) {
+ ReleaseWriteLock(&afs_xcell);
+ return lookupcode;
+ }
+
+ tfile = osi_UFSOpen(inode);
+ if (!tfile) {
+ ReleaseWriteLock(&afs_xcell);
+ return EIO;
+ }
+
+ 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));
+ if (cc != sizeof(magic))
+ break;
+ if (magic != AFS_CELLINFO_MAGIC)
+ break;
+ off += cc;
+
+ cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
+ if (cc != sizeof(cellnum))
+ break;
+ off += cc;
+
+ cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
+ if (cc != sizeof(clen))
+ break;
+ off += cc;
+
+ cellname = afs_osi_Alloc(clen + 1);
+ if (!cellname)
+ break;
+
+ cc = afs_osi_Read(tfile, off, cellname, clen);
+ if (cc != clen) {
+ afs_osi_Free(cellname, clen + 1);
+ break;
}
+ off += cc;
+ cellname[clen] = '\0';
- afs_PutCell(tc, READ_LOCK);
+ 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_osi_Free(cellname, clen + 1);
}
- if (realName)
- afs_osi_Free(realName, strlen(realName) + 1);
- return afs_FindCellByName(acellName, locktype);
+ osi_UFSClose(tfile);
+ ReleaseWriteLock(&afs_xcell);
+ return 0;
+}
-bad:
- if (realName)
- afs_osi_Free(realName, strlen(realName) + 1);
- return NULL;
+int afs_cellname_write()
+{
+ struct osi_file *tfile;
+ struct cell_name *cn;
+ int code, off;
+
+ if (!afs_cellname_dirty || !afs_cellname_inode_set)
+ return 0;
+ if (afs_initState != 300)
+ return 0;
+
+ ObtainWriteLock(&afs_xcell, 693);
+ afs_cellname_dirty = 0;
+ off = 0;
+ tfile = osi_UFSOpen(afs_cellname_inode);
+ if (!tfile) {
+ ReleaseWriteLock(&afs_xcell);
+ return EIO;
+ }
+
+ for (cn = afs_cellname_head; cn; cn = cn->next) {
+ afs_int32 magic, cellnum, clen;
+ int cc;
+
+ if (!cn->used)
+ continue;
+
+ magic = AFS_CELLINFO_MAGIC;
+ cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
+ if (cc != sizeof(magic))
+ break;
+ off += cc;
+
+ cellnum = cn->cellnum;
+ cc = afs_osi_Write(tfile, off, &cellnum, sizeof(cellnum));
+ if (cc != sizeof(cellnum))
+ break;
+ off += cc;
+
+ clen = strlen(cn->cellname);
+ cc = afs_osi_Write(tfile, off, &clen, sizeof(clen));
+ if (cc != sizeof(clen))
+ break;
+ off += cc;
+
+ cc = afs_osi_Write(tfile, off, cn->cellname, clen);
+ if (cc != clen)
+ break;
+ off += clen;
+ }
+
+ osi_UFSClose(tfile);
+ ReleaseWriteLock(&afs_xcell);
+ return 0;
}
+/*
+ * Cell alias implementation
+ *
+ * afs_FindCellAlias: look up cell alias by alias name
+ * afs_GetCellAlias: get cell alias by index (starting at 0)
+ * afs_PutCellAlias: put back a cell alias returned by Find or Get
+ * afs_NewCellAlias: create new cell alias entry
+ */
-struct cell *afs_FindCellByName(register char *acellName, afs_int32 locktype)
+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 struct cell_alias *afs_FindCellAlias(char *alias)
{
- register struct cell *tc;
- register struct afs_q *cq, *tq;
- int didAlias = 0;
+ struct cell_alias *tc;
- AFS_STATCNT(afs_GetCellByName);
-retry:
- ObtainWriteLock(&afs_xcell,100);
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
- if (!afs_strcasecmp(tc->cellName, acellName)) {
- QRemove(&tc->lruq);
- QAdd(&CellLRU, &tc->lruq);
- ReleaseWriteLock(&afs_xcell);
- afs_RefreshCell(tc);
- if ((tc->states & CAlias) && (didAlias == 0)) {
- acellName = tc->realName;
- if (!acellName) return NULL;
- didAlias = 1;
- goto retry;
- }
- return tc;
- }
+ for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
+ if (!strcmp(alias, tc->alias))
+ break;
+ return tc;
+}
+
+struct cell_alias *afs_GetCellAlias(int index)
+{
+ struct cell_alias *tc;
+
+ ObtainReadLock(&afs_xcell);
+ for (tc = afs_cellalias_head; tc != NULL; tc = tc->next)
+ if (tc->index == index)
+ break;
+ ReleaseReadLock(&afs_xcell);
+
+ return tc;
+}
+
+void afs_PutCellAlias(struct cell_alias *a)
+{
+ return;
+}
+
+afs_int32 afs_NewCellAlias(char *alias, char *cell)
+{
+ struct cell_alias *tc;
+
+ ObtainSharedLock(&afs_xcell, 681);
+ if (afs_CellOrAliasExists_nl(alias)) {
+ ReleaseSharedLock(&afs_xcell);
+ return EEXIST;
}
+ UpgradeSToWLock(&afs_xcell, 682);
+ tc = (struct cell_alias *) afs_osi_Alloc(sizeof(struct cell_alias));
+ tc->alias = afs_strdup(alias);
+ tc->cell = afs_strdup(cell);
+ tc->next = afs_cellalias_head;
+ tc->index = afs_cellalias_index++;
+ afs_cellalias_head = tc;
ReleaseWriteLock(&afs_xcell);
- return NULL;
+
+ afs_DynrootInvalidate();
+ return 0;
}
-struct cell *afs_GetCellByName(register char *acellName, afs_int32 locktype)
+/*
+ * Actual cell list implementation
+ *
+ * afs_UpdateCellLRU: bump given cell up to the front of the LRU queue
+ * afs_RefreshCell: look up cell information in AFSDB if timeout expired
+ *
+ * afs_TraverseCells: execute a callback for each existing cell
+ * afs_TraverseCells_nl: same as above except without locking afs_xcell
+ * afs_choose_cell_by_{name,num,index}: useful traversal callbacks
+ *
+ * afs_FindCellByName: return a cell with a given name, if it exists
+ * afs_FindCellByName_nl: same as above, without locking afs_xcell
+ * afs_GetCellByName: same as FindCellByName but tries AFSDB if not found
+ * afs_GetCell: return a cell with a given cell number
+ * afs_GetCellStale: same as GetCell, but does not try to refresh the data
+ * afs_GetCellByIndex: return a cell with a given index number (starting at 0)
+ *
+ * afs_GetPrimaryCell: return the primary cell, if any
+ * afs_IsPrimaryCell: returns true iff the given cell is the primary cell
+ * afs_IsPrimaryCellNum: returns afs_IsPrimaryCell(afs_GetCell(cellnum))
+ * afs_SetPrimaryCell: set the primary cell name to the given cell name
+ *
+ * afs_NewCell: create or update a cell entry
+ */
+
+struct afs_q CellLRU; /* Export for kdump */
+static char *afs_thiscell;
+static afs_int32 afs_cellindex;
+
+static void afs_UpdateCellLRU(struct cell *c)
{
- struct cell *tc;
+ ObtainWriteLock(&afs_xcell, 100);
+ QRemove(&c->lruq);
+ QAdd(&CellLRU, &c->lruq);
+ ReleaseWriteLock(&afs_xcell);
+}
- tc = afs_FindCellByName(acellName, locktype);
- if (!tc)
- tc = afs_GetCellByName_Dns(acellName, locktype);
-
- return tc;
+static void afs_RefreshCell(struct cell *ac)
+{
+ if (ac->states & CNoAFSDB)
+ return;
+ if (!ac->cellHosts[0] || (ac->timeout && ac->timeout <= osi_Time()))
+ afs_LookupAFSDB(ac->cellName);
}
-static struct cell *afs_GetCellInternal(register afs_int32 acell,
- afs_int32 locktype, int holdxcell)
+static void *afs_TraverseCells_nl(void *(*cb)(struct cell *, void *), void *arg)
{
- register struct cell *tc;
- register struct afs_q *cq, *tq;
+ struct afs_q *cq, *tq;
+ struct cell *tc;
+ void *ret = NULL;
- AFS_STATCNT(afs_GetCell);
- if (acell == 1 && afs_rootcell) return afs_rootcell;
- if (holdxcell)
- ObtainWriteLock(&afs_xcell,101);
for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
tc = QTOC(cq); tq = QNext(cq);
- if (tc->cell == acell) {
- QRemove(&tc->lruq);
- QAdd(&CellLRU, &tc->lruq);
- if (holdxcell)
- ReleaseWriteLock(&afs_xcell);
- afs_RefreshCell(tc);
- return tc;
- }
+ ret = cb(tc, arg);
+ if (ret) break;
}
- if (holdxcell)
- ReleaseWriteLock(&afs_xcell);
- return NULL;
+ return ret;
}
-struct cell *afs_GetCell(register afs_int32 acell, afs_int32 locktype)
+void *afs_TraverseCells(void *(*cb)(struct cell *, void *), void *arg)
{
- return afs_GetCellInternal(acell, locktype, 1);
+ void *ret;
+
+ ObtainReadLock(&afs_xcell);
+ ret = afs_TraverseCells_nl(cb, arg);
+ ReleaseReadLock(&afs_xcell);
+
+ return ret;
}
-/* This is only to be called if the caller is already holding afs_xcell */
-struct cell *afs_GetCellNoLock(register afs_int32 acell, afs_int32 locktype)
+static void *afs_choose_cell_by_name(struct cell *cell, void *arg)
{
- return afs_GetCellInternal(acell, locktype, 0);
+ return strcmp(cell->cellName, (char *) arg) ? NULL : cell;
}
-struct cell *afs_GetCellByIndex(register afs_int32 cellindex,
- afs_int32 locktype, afs_int32 refresh)
+static void *afs_choose_cell_by_num(struct cell *cell, void *arg)
{
- register struct cell *tc;
- register struct afs_q *cq, *tq;
+ return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
+}
- AFS_STATCNT(afs_GetCellByIndex);
- ObtainWriteLock(&afs_xcell,102);
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
- if (tc->cellIndex == cellindex) {
- QRemove(&tc->lruq);
- QAdd(&CellLRU, &tc->lruq);
- ReleaseWriteLock(&afs_xcell);
- if (refresh) afs_RefreshCell(tc);
- return tc;
- }
+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 afs_TraverseCells_nl(&afs_choose_cell_by_name, acellName);
+}
+
+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)
+{
+ struct cell *tc;
+
+ tc = afs_FindCellByName(acellName, locktype);
+ if (!tc) {
+ afs_LookupAFSDB(acellName);
+ tc = afs_FindCellByName(acellName, locktype);
+ }
+ if (tc) {
+ afs_cellname_ref(tc->cnamep);
+ afs_UpdateCellLRU(tc);
+ afs_RefreshCell(tc);
}
- ReleaseWriteLock(&afs_xcell);
- return NULL;
+ return tc;
}
+struct cell *afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
+{
+ struct cell *tc;
+ struct cell_name *cn;
-struct cell *afs_GetRealCellByIndex(register afs_int32 cellindex, afs_int32 locktype, afs_int32 refresh)
+ tc = afs_GetCellStale(cellnum, locktype);
+ if (tc) {
+ afs_RefreshCell(tc);
+ } else {
+ ObtainReadLock(&afs_xcell);
+ cn = afs_cellname_lookup_id(cellnum);
+ ReleaseReadLock(&afs_xcell);
+ if (cn)
+ tc = afs_GetCellByName(cn->cellname, locktype);
+ }
+ return tc;
+}
+
+struct cell *afs_GetCellStale(afs_int32 cellnum, afs_int32 locktype)
{
- register struct cell *tc;
- register struct afs_q *cq, *tq;
+ struct cell *tc;
- AFS_STATCNT(afs_GetCellByIndex);
- ObtainWriteLock(&afs_xcell,102);
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
- if (tc->realcellIndex == cellindex) {
- QRemove(&tc->lruq);
- QAdd(&CellLRU, &tc->lruq);
- ReleaseWriteLock(&afs_xcell);
- if (refresh) afs_RefreshCell(tc);
- return tc;
- }
+ tc = afs_TraverseCells(&afs_choose_cell_by_num, &cellnum);
+ if (tc) {
+ afs_cellname_ref(tc->cnamep);
+ afs_UpdateCellLRU(tc);
}
- ReleaseWriteLock(&afs_xcell);
- return NULL;
-} /*afs_GetRealCellByIndex*/
+ return tc;
+}
+
+struct cell *afs_GetCellByIndex(afs_int32 index, afs_int32 locktype)
+{
+ struct cell *tc;
+ tc = afs_TraverseCells(&afs_choose_cell_by_index, &index);
+ if (tc)
+ afs_UpdateCellLRU(tc);
+ return tc;
+}
-afs_int32 afs_NewCell(char *acellName, register afs_int32 *acellHosts, int aflags,
- char *linkedcname, u_short fsport, u_short vlport, int timeout, char *aliasFor)
+struct cell *afs_GetPrimaryCell(afs_int32 locktype)
{
- register struct cell *tc, *tcl=0;
- register afs_int32 i, newc=0, code=0;
- register struct afs_q *cq, *tq;
+ return afs_GetCellByName(afs_thiscell, locktype);
+}
- AFS_STATCNT(afs_NewCell);
+int afs_IsPrimaryCell(struct cell *cell)
+{
+ return strcmp(cell->cellName, afs_thiscell) ? 0 : 1;
+}
- ObtainWriteLock(&afs_xcell,103);
+int afs_IsPrimaryCellNum(afs_int32 cellnum)
+{
+ struct cell *tc;
+ int primary = 0;
- /* Find the cell and mark its servers as not down but gone */
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
- if (afs_strcasecmp(tc->cellName, acellName) == 0) {
- /* If the cell we've found has the correct name but no timeout,
- * and we're called with a non-zero timeout, bail out: never
- * override static configuration entries with AFSDB ones.
- * One exception: if the original cell entry had no servers,
- * it must get servers from AFSDB.
- */
- if (timeout && !tc->timeout && tc->cellHosts[0]) {
- ReleaseWriteLock(&afs_xcell);
- return 0;
- }
- /* 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;
- tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
- tc->cellHosts[i]->flags |= SRVR_ISGONE;
- }
- break;
- }
+ tc = afs_GetCellStale(cellnum, READ_LOCK);
+ if (tc) {
+ primary = afs_IsPrimaryCell(tc);
+ afs_PutCell(tc, READ_LOCK);
}
- if (cq != &CellLRU) {
+ return primary;
+}
+
+afs_int32 afs_SetPrimaryCell(char *acellName)
+{
+ ObtainWriteLock(&afs_xcell, 691);
+ if (afs_thiscell)
+ afs_osi_FreeStr(afs_thiscell);
+ afs_thiscell = afs_strdup(acellName);
+ ReleaseWriteLock(&afs_xcell);
+ return 0;
+}
+
+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;
+
+ AFS_STATCNT(afs_NewCell);
+
+ ObtainWriteLock(&afs_xcell, 103);
+
+ tc = afs_FindCellByName_nl(acellName, READ_LOCK);
+ if (tc) {
aflags &= ~CNoSUID;
- }
- else {
+ } else {
tc = (struct cell *) afs_osi_Alloc(sizeof(struct cell));
- memset((char *)tc, 0, sizeof(*tc));
- QAdd(&CellLRU, &tc->lruq); /* put in lruq */
- tc->cellName = (char *) afs_osi_Alloc(strlen(acellName)+1);
- strcpy(tc->cellName, acellName);
- tc->cellIndex = afs_cellindex++;
- if (aflags & CPrimary) {
- extern int afs_rootCellIndex;
- tc->cell = 1; /* primary cell is always 1 */
- afs_rootcell = tc;
- afs_rootCellIndex = tc->cellIndex;
- } else {
- tc->cell = afs_nextCellNum++;
- }
- tc->states = 0;
- tc->lcellp = NULL;
- tc->fsport = (fsport ? fsport : AFS_FSPORT);
- tc->vlport = (vlport ? vlport : AFS_VLPORT);
- afs_stats_cmperf.numCellsVisible++;
- newc++;
- if (!(aflags & CAlias)) {
- tc->realcellIndex = afs_realcellindex++;
- } else {
- tc->realcellIndex = -1;
- }
+ memset((char *) tc, 0, sizeof(*tc));
+ tc->cellName = afs_strdup(acellName);
+ tc->fsport = AFS_FSPORT;
+ tc->vlport = AFS_VLPORT;
+ RWLOCK_INIT(&tc->lock, "cell lock");
+ newc = 1;
+ if (afs_thiscell && !strcmp(acellName, afs_thiscell))
+ aflags &= ~CNoSUID;
+ }
+ ObtainWriteLock(&tc->lock, 688);
+
+ /* If the cell we've found has the correct name but no timeout,
+ * and we're called with a non-zero timeout, bail out: never
+ * override static configuration entries with AFSDB ones.
+ * One exception: if the original cell entry had no servers,
+ * it must get servers from AFSDB.
+ */
+ if (timeout && !tc->timeout && tc->cellHosts[0]) {
+ code = EINVAL;
+ 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;
+ tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
+ tc->cellHosts[i]->flags |= SRVR_ISGONE;
}
+ if (fsport) tc->fsport = fsport;
+ if (vlport) tc->vlport = vlport;
+
if (aflags & CLinkedCell) {
if (!linkedcname) {
code = EINVAL;
goto bad;
}
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tcl = QTOC(cq); tq = QNext(cq);
- if (!afs_strcasecmp(tcl->cellName, linkedcname)) {
- break;
- }
- tcl = 0;
- }
+ tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
if (!tcl) {
code = ENOENT;
goto bad;
}
if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */
- tcl->lcellp->lcellp = NULL;
+ tcl->lcellp->lcellp = (struct cell *)0;
tcl->lcellp->states &= ~CLinkedCell;
}
tc->lcellp = tcl;
tc->states |= aflags;
tc->timeout = timeout;
- /* Allow converting an alias into a real cell */
- if ((!(aflags & CAlias)) && (tc->states & CAlias)) {
- tc->states &= ~CAlias;
- tc->realcellIndex = afs_realcellindex++;
- }
-
memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts));
- if (aflags & CAlias) {
- if (!aliasFor) {
- code = EINVAL;
- goto bad;
- }
- if (tc->realName) afs_osi_Free(tc->realName, strlen(tc->realName)+1);
- tc->realName = (char *) afs_osi_Alloc(strlen(aliasFor)+1);
- strcpy(tc->realName, aliasFor);
- goto done;
- }
-
for (i=0; i<MAXCELLHOSTS; i++) {
- struct server *ts;
+ struct server *ts;
afs_uint32 temp = acellHosts[i];
if (!temp) break;
- ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, (afsUUID *)0, 0);
- ts->cell = tc;
+ ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
+ ts->cell = tc;
ts->flags &= ~SRVR_ISGONE;
tc->cellHosts[i] = ts;
afs_PutServer(ts, WRITE_LOCK);
}
afs_SortServers(tc->cellHosts, MAXCELLHOSTS); /* randomize servers */
-done:
+
+ if (newc) {
+ struct cell_name *cn;
+
+ cn = afs_cellname_lookup_name(acellName);
+ if (!cn)
+ cn = afs_cellname_new(acellName, 0);
+
+ tc->cnamep = cn;
+ tc->cellNum = cn->cellnum;
+ tc->cellIndex = afs_cellindex++;
+ afs_stats_cmperf.numCellsVisible++;
+ QAdd(&CellLRU, &tc->lruq);
+ }
+
+ ReleaseWriteLock(&tc->lock);
ReleaseWriteLock(&afs_xcell);
+ afs_PutCell(tc, 0);
+ afs_DynrootInvalidate();
return 0;
+
bad:
if (newc) {
- QRemove(&tc->lruq);
- afs_osi_Free(tc->cellName, strlen(tc->cellName)+1);
- afs_osi_Free((char *)tc, sizeof(struct cell));
+ afs_osi_FreeStr(tc->cellName);
+ afs_osi_Free(tc, sizeof(struct cell));
}
+ ReleaseWriteLock(&tc->lock);
ReleaseWriteLock(&afs_xcell);
return code;
}
+/*
+ * Miscellaneous stuff
+ *
+ * afs_CellInit: perform whatever initialization is necessary
+ * shutdown_cell: called on shutdown, should deallocate memory, etc
+ * afs_RemoveCellEntry: remove a server from a cell's server list
+ * afs_CellOrAliasExists: check if the given name exists as a cell or alias
+ * afs_CellOrAliasExists_nl: same as above without locking afs_xcell
+ * afs_CellNumValid: check if a cell number is valid (also set the used flag)
+ */
+
+void afs_CellInit()
+{
+ RWLOCK_INIT(&afs_xcell, "afs_xcell");
+#ifdef AFS_AFSDB_ENV
+ RWLOCK_INIT(&afsdb_req.lock, "afsdb_req.lock");
+#endif
+ QInit(&CellLRU);
+
+ afs_cellindex = 0;
+ afs_cellalias_index = 0;
+}
+
+void shutdown_cell()
+{
+ struct afs_q *cq, *tq;
+ struct cell *tc;
+
+ 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);
+ afs_osi_Free(tc, sizeof(struct cell));
+ }
+ QInit(&CellLRU);
+}
+
void afs_RemoveCellEntry(struct server *srvp)
{
- struct cell *tc;
- afs_int32 j, k;
-
- tc = srvp->cell;
- if (!tc) return;
-
- /* Remove the server structure from the cell list - if there */
- ObtainWriteLock(&afs_xcell,200);
- for (j=k=0; j<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++) {
- tc->cellHosts[k] = 0;
- }
- ReleaseWriteLock(&afs_xcell);
+ struct cell *tc;
+ afs_int32 j, k;
+
+ tc = srvp->cell;
+ 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;
+ 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++) {
+ tc->cellHosts[k] = 0;
+ }
+ ReleaseWriteLock(&tc->lock);
}
+static int afs_CellOrAliasExists_nl(char *aname)
+{
+ struct cell *c;
+ struct cell_alias *ca;
+
+ c = afs_FindCellByName_nl(aname, READ_LOCK);
+ if (c) {
+ afs_PutCell(c, READ_LOCK);
+ return 1;
+ }
+
+ ca = afs_FindCellAlias(aname);
+ if (ca) {
+ afs_PutCellAlias(ca);
+ return 1;
+ }
+
+ return 0;
+}
+
+int afs_CellOrAliasExists(char *aname)
+{
+ int ret;
+
+ ObtainReadLock(&afs_xcell);
+ ret = afs_CellOrAliasExists_nl(aname);
+ ReleaseReadLock(&afs_xcell);
+
+ return ret;
+}
+
+int afs_CellNumValid(afs_int32 cellnum)
+{
+ struct cell_name *cn;
+
+ ObtainReadLock(&afs_xcell);
+ cn = afs_cellname_lookup_id(cellnum);
+ ReleaseReadLock(&afs_xcell);
+ if (cn) {
+ cn->used = 1;
+ return 1;
+ } else {
+ return 0;
+ }
+}
int afs_CheckRootVolume (void)
{
char rootVolName[32];
- register struct volume *tvp;
+ struct volume *tvp = NULL;
int usingDynroot = afs_GetDynrootEnable();
+ int localcell;
AFS_STATCNT(afs_CheckRootVolume);
if (*afs_rootVolumeName == 0) {
strcpy(rootVolName, "root.afs");
- }
- else {
+ } else {
strcpy(rootVolName, afs_rootVolumeName);
}
+
+ if (!usingDynroot) {
+ struct cell *lc = afs_GetPrimaryCell(READ_LOCK);
+
+ if (!lc)
+ return ENOENT;
+ localcell = lc->cellNum;
+ afs_PutCell(lc, READ_LOCK);
+ }
+
if (usingDynroot) {
afs_GetDynrootFid(&afs_rootFid);
tvp = afs_GetVolume(&afs_rootFid, NULL, READ_LOCK);
} else {
- tvp = afs_GetVolumeByName(rootVolName, LOCALCELL, 1, NULL, READ_LOCK);
+ tvp = afs_GetVolumeByName(rootVolName, localcell, 1, NULL, READ_LOCK);
}
- if (!tvp) {
+ if (!tvp && !usingDynroot) {
char buf[128];
int len = strlen(rootVolName);
if ((len < 9) || strcmp(&rootVolName[len - 9], ".readonly")) {
strcpy(buf, rootVolName);
afs_strcat(buf, ".readonly");
- tvp = afs_GetVolumeByName(buf, LOCALCELL, 1, NULL, READ_LOCK);
+ tvp = afs_GetVolumeByName(buf, localcell, 1, NULL, READ_LOCK);
}
}
if (tvp) {
if (!usingDynroot) {
int volid = (tvp->roVol? tvp->roVol : tvp->volume);
- afs_rootFid.Cell = LOCALCELL;
+ afs_rootFid.Cell = localcell;
if (afs_rootFid.Fid.Volume && afs_rootFid.Fid.Volume != volid
&& afs_globalVp) {
/* If we had a root fid before and it changed location we reset
/*
* See if this was a reference to a file in the local cell.
*/
- if (avc->fid.Cell == LOCALCELL)
+ if (afs_IsPrimaryCellNum(avc->fid.Cell))
afs_stats_cmperf.dlocalAccesses++;
else
afs_stats_cmperf.dremoteAccesses++;
register afs_int32 code;
register struct dcache *tdc;
int existing = 0;
+ int entryok;
AFS_STATCNT(afs_UFSGetDSlot);
if (CheckLock(&afs_xdcache) != -1) osi_Panic("getdslot nolock");
/*
* Seek to the aslot'th entry and read it in.
*/
- code = afs_osi_Read(afs_cacheInodep, sizeof(struct fcache) * aslot + sizeof(struct afs_fheader),
- (char *)(&tdc->f), sizeof(struct fcache));
- if (code != sizeof(struct fcache)) {
+ code = afs_osi_Read(afs_cacheInodep, sizeof(struct fcache) * aslot +
+ sizeof(struct afs_fheader),
+ (char *)(&tdc->f), sizeof(struct fcache));
+ entryok = 1;
+ if (code != sizeof(struct fcache))
+ entryok = 0;
+ if (!afs_CellNumValid(tdc->f.fid.Cell))
+ entryok = 0;
+
+ if (!entryok) {
tdc->f.fid.Cell = 0;
tdc->f.fid.Fid.Volume = 0;
tdc->f.chunk = -1;
/*
* Seek to the right dcache slot and write the in-memory image out to disk.
*/
- code = afs_osi_Write(afs_cacheInodep, sizeof(struct fcache) * adc->index + sizeof(struct afs_fheader),
- (char *)(&adc->f), sizeof(struct fcache));
+ afs_cellname_write();
+ code = afs_osi_Write(afs_cacheInodep, sizeof(struct fcache) * adc->index +
+ sizeof(struct afs_fheader),
+ (char *)(&adc->f), sizeof(struct fcache));
if (code != sizeof(struct fcache)) return EIO;
return 0;
}
* afs_IsDynrootFid
* afs_GetDynrootFid
* afs_IsDynroot
- * afs_RefreshDynroot
+ * afs_DynrootInvalidate
* afs_GetDynroot
* afs_PutDynroot
* afs_DynrootNewVnode
#include "../afs/prs_fs.h"
#include "../afs/dir.h"
-#define AFS_DYNROOT_CELL 1
+#define AFS_DYNROOT_CELLNAME "dynroot"
#define AFS_DYNROOT_VOLUME 1
#define AFS_DYNROOT_VNODE 1
#define AFS_DYNROOT_UNIQUE 1
* and a type-specific identifier in the lower 24 bits.
*/
#define VN_TYPE_CELL 0x01 /* Corresponds to a struct cell */
-#define VN_TYPE_SYMLINK 0x02 /* User-created symlink in /afs */
+#define VN_TYPE_ALIAS 0x02 /* Corresponds to a struct cell_alias */
+#define VN_TYPE_SYMLINK 0x03 /* User-created symlink in /afs */
#define VNUM_TO_VNTYPE(vnum) ((vnum) >> 24)
#define VNUM_TO_VNID(vnum) ((vnum) & 0x00ffffff)
#define VNUM_FROM_CIDX_RW(cidx, rw) \
VNUM_FROM_TYPEID(VN_TYPE_CELL, \
((cidx) << 2 | (rw) << 1))
+#define VNUM_FROM_CAIDX_RW(caidx, rw) \
+ VNUM_FROM_TYPEID(VN_TYPE_ALIAS, \
+ ((caidx) << 2 | (rw) << 1))
static int afs_dynrootEnable = 0;
+static int afs_dynrootCell = 0;
static afs_rwlock_t afs_dynrootDirLock;
/* Start of variables protected by afs_dynrootDirLock */
static char *afs_dynrootDir = NULL;
static int afs_dynrootDirLen;
static int afs_dynrootDirLinkcnt;
-static int afs_dynrootCellCount;
+static int afs_dynrootDirVersion;
static int afs_dynrootVersion = 1;
static int afs_dynrootVersionHigh = 1;
/* End of variables protected by afs_dynrootDirLock */
/* End of variables protected by afs_dynSymlinkLock */
/*
+ * Set up a cell for dynroot if it's not there yet.
+ */
+static int afs_dynrootCellInit()
+{
+ if (afs_dynrootEnable && !afs_dynrootCell) {
+ afs_int32 cellHosts[MAXCELLHOSTS];
+ struct cell *tc;
+ int code;
+
+ memset(cellHosts, 0, sizeof(cellHosts));
+ code = afs_NewCell(AFS_DYNROOT_CELLNAME, cellHosts, CNoSUID | CNoAFSDB,
+ NULL, 0, 0, 0);
+ if (code)
+ return code;
+ tc = afs_GetCellByName(AFS_DYNROOT_CELLNAME, READ_LOCK);
+ if (!tc)
+ return ENODEV;
+ afs_dynrootCell = tc->cellNum;
+ afs_PutCell(tc, READ_LOCK);
+ }
+
+ return 0;
+}
+
+/*
* Returns non-zero iff fid corresponds to the top of the dynroot volume.
*/
int afs_IsDynrootFid(struct VenusFid *fid)
{
return
(afs_dynrootEnable &&
- fid->Cell == AFS_DYNROOT_CELL &&
+ fid->Cell == afs_dynrootCell &&
fid->Fid.Volume == AFS_DYNROOT_VOLUME &&
fid->Fid.Vnode == AFS_DYNROOT_VNODE &&
fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
*/
void afs_GetDynrootFid(struct VenusFid *fid)
{
- fid->Cell = AFS_DYNROOT_CELL;
+ fid->Cell = afs_dynrootCell;
fid->Fid.Volume = AFS_DYNROOT_VOLUME;
fid->Fid.Vnode = AFS_DYNROOT_VNODE;
fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
}
/*
+ * Invalidate the /afs vnode for dynroot; called when the underlying
+ * directory has changed and needs to be re-read.
+ */
+void afs_DynrootInvalidate(void)
+{
+ afs_int32 retry;
+ struct vcache *tvc;
+ struct VenusFid tfid;
+
+ if (!afs_dynrootEnable)
+ return;
+
+ ObtainWriteLock(&afs_dynrootDirLock, 687);
+ afs_dynrootVersion++;
+ afs_dynrootVersionHigh = osi_Time();
+ ReleaseWriteLock(&afs_dynrootDirLock);
+
+ afs_GetDynrootFid(&tfid);
+ do {
+ retry = 0;
+ ObtainReadLock(&afs_xvcache);
+ tvc = afs_FindVCache(&tfid, &retry, 0);
+ ReleaseReadLock(&afs_xvcache);
+ } while (retry);
+ if (tvc) {
+ tvc->states &= ~(CStatd | CUnique);
+ osi_dnlc_purgedp(tvc);
+ afs_PutVCache(tvc);
+ }
+}
+
+/*
* Regenerates the dynroot contents from the current list of
* cells. Useful when the list of cells has changed due to
* an AFSDB lookup, for instance.
*/
-void afs_RefreshDynroot(void)
+static void afs_RebuildDynroot(void)
{
int cellidx, maxcellidx, i;
+ int aliasidx, maxaliasidx;
struct cell *c;
+ struct cell_alias *ca;
int curChunk, curPage;
int dirSize, sizeOfCurEntry;
char *newDir, *dotCell;
struct DirHeader *dirHeader;
- int doFlush = 0;
int linkCount = 0;
struct afs_dynSymlink *ts;
- int newCellCount;
+ int newVersion;
- /*
- * Save afs_cellindex here, in case it changes between the
- * two loops.
- */
- maxcellidx = afs_cellindex;
+ ObtainReadLock(&afs_dynrootDirLock);
+ newVersion = afs_dynrootVersion;
+ ReleaseReadLock(&afs_dynrootDirLock);
/*
* Compute the amount of space we need for the fake dir
/* Reserve space for "." and ".." */
curChunk += 2;
- for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
- c = afs_GetCellByIndex(cellidx, READ_LOCK, 0 /* don't refresh */);
- if (!c) continue;
+ for (cellidx = 0; ; cellidx++) {
+ c = afs_GetCellByIndex(cellidx, READ_LOCK);
+ if (!c) break;
+ if (c->cellNum == afs_dynrootCell) continue;
sizeOfCurEntry = afs_dir_NameBlobs(c->cellName);
if (curChunk + sizeOfCurEntry > EPP) {
afs_PutCell(c, READ_LOCK);
}
+ maxcellidx = cellidx;
+
+ for (aliasidx = 0; ; aliasidx++) {
+ ca = afs_GetCellAlias(aliasidx);
+ if (!ca) break;
+
+ sizeOfCurEntry = afs_dir_NameBlobs(ca->alias);
+ if (curChunk + sizeOfCurEntry > EPP) {
+ curPage++;
+ curChunk = 1;
+ }
+ curChunk += sizeOfCurEntry;
+
+ dotCell = afs_osi_Alloc(strlen(ca->alias) + 2);
+ strcpy(dotCell, ".");
+ strcat(dotCell, ca->alias);
+ sizeOfCurEntry = afs_dir_NameBlobs(dotCell);
+ if (curChunk + sizeOfCurEntry > EPP) {
+ curPage++;
+ curChunk = 1;
+ }
+ curChunk += sizeOfCurEntry;
+
+ afs_PutCellAlias(ca);
+ }
+ maxaliasidx = aliasidx;
ObtainReadLock(&afs_dynSymlinkLock);
ts = afs_dynSymlinkBase;
linkCount += 2;
for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
- c = afs_GetCellByIndex(cellidx, READ_LOCK, 0 /* don't refresh */);
+ c = afs_GetCellByIndex(cellidx, READ_LOCK);
if (!c) continue;
+ if (c->cellNum == afs_dynrootCell) continue;
dotCell = afs_osi_Alloc(strlen(c->cellName) + 2);
strcpy(dotCell, ".");
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
dotCell, VNUM_FROM_CIDX_RW(cellidx, 1));
- if (!(c->states & CAlias)) linkCount += 2;
+ linkCount += 2;
afs_PutCell(c, READ_LOCK);
}
+ for (aliasidx = 0; aliasidx < maxaliasidx; aliasidx++) {
+ ca = afs_GetCellAlias(aliasidx);
+ if (!ca) continue;
+
+ dotCell = afs_osi_Alloc(strlen(ca->alias) + 2);
+ strcpy(dotCell, ".");
+ strcat(dotCell, ca->alias);
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
+ ca->alias, VNUM_FROM_CAIDX_RW(aliasidx, 0));
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
+ dotCell, VNUM_FROM_CAIDX_RW(aliasidx, 1));
+ afs_PutCellAlias(ca);
+ }
+
ts = afs_dynSymlinkBase;
while (ts) {
int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index);
ts = ts->next;
}
- newCellCount = maxcellidx + afs_dynSymlinkIndex;
ReleaseReadLock(&afs_dynSymlinkLock);
ObtainWriteLock(&afs_dynrootDirLock, 549);
afs_dynrootDir = newDir;
afs_dynrootDirLen = dirSize;
afs_dynrootDirLinkcnt = linkCount;
- if (afs_dynrootCellCount != newCellCount) {
- /*
- * New cells/symlinks added -- bump data version, invalidate vcache.
- */
- afs_dynrootCellCount = newCellCount;
- afs_dynrootVersion++;
- afs_dynrootVersionHigh = osi_Time();
- doFlush = 1;
- }
+ afs_dynrootDirVersion = newVersion;
ReleaseWriteLock(&afs_dynrootDirLock);
-
- if (doFlush) {
- afs_int32 retry;
- struct vcache *tvc;
- struct VenusFid tfid;
-
- afs_GetDynrootFid(&tfid);
- do {
- retry = 0;
- ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(&tfid, &retry, 0);
- ReleaseReadLock(&afs_xvcache);
- } while (retry);
- if (tvc) {
- tvc->states &= ~(CStatd | CUnique);
- osi_dnlc_purgedp(tvc);
- afs_PutVCache(tvc);
- }
- }
}
/*
* Returns a pointer to the base of the dynroot directory in memory,
* length thereof, and a FetchStatus.
*/
-void afs_GetDynroot(char **dynrootDir, int *dynrootLen, struct AFSFetchStatus *status)
+void afs_GetDynroot(char **dynrootDir, int *dynrootLen,
+ struct AFSFetchStatus *status)
{
ObtainReadLock(&afs_dynrootDirLock);
- if (!afs_dynrootDir) {
+ if (!afs_dynrootDir || afs_dynrootDirVersion != afs_dynrootVersion) {
ReleaseReadLock(&afs_dynrootDirLock);
- afs_RefreshDynroot();
+ afs_RebuildDynroot();
ObtainReadLock(&afs_dynrootDirLock);
}
/*
* Check if this is an entry under /afs, e.g. /afs/cellname.
*/
- if (avc->fid.Cell == AFS_DYNROOT_CELL &&
+ if (avc->fid.Cell == afs_dynrootCell &&
avc->fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
struct cell *c;
+ struct cell_alias *ca;
int namelen, linklen, cellidx, rw;
memset(status, 0, sizeof(struct AFSFetchStatus));
return ts ? 1 : 0;
}
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_CELL) {
+ if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_CELL &&
+ VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_ALIAS) {
afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n",
VNUM_TO_VNTYPE(avc->fid.Fid.Vnode));
return 0;
cellidx = VNUM_TO_CIDX(avc->fid.Fid.Vnode);
rw = VNUM_TO_RW(avc->fid.Fid.Vnode);
- c = afs_GetCellByIndex(cellidx, READ_LOCK, 1 /* refresh */);
- if (!c) {
- afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
- cellidx);
- return 0;
- }
+ if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_ALIAS) {
+ char *realName;
+
+ ca = afs_GetCellAlias(cellidx);
+ if (!ca) {
+ afs_warn("dynroot vnode inconsistency, can't find alias %d\n",
+ cellidx);
+ return 0;
+ }
- if (c->states & CAlias) {
/*
* linkData needs to contain the name of the cell
* we're aliasing for.
*/
- char *realName = c->realName;
-
+ realName = ca->cell;
if (!realName) {
afs_warn("dynroot: alias %s missing real cell name\n",
- c->cellName);
+ ca->alias);
+ avc->linkData = afs_strdup("unknown");
linklen = 7;
- avc->linkData = afs_osi_Alloc(linklen + 1);
- strcpy(avc->linkData, "unknown");
} else {
int namelen = strlen(realName);
linklen = rw + namelen;
}
status->UnixModeBits = 0755;
+ afs_PutCellAlias(ca);
} else {
+ c = afs_GetCellByIndex(cellidx, READ_LOCK);
+ if (!c) {
+ afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
+ cellidx);
+ return 0;
+ }
+
/*
* linkData needs to contain "#cell:root.cell" or "%cell:root.cell"
*/
strcat(avc->linkData, ":root.cell");
status->UnixModeBits = 0644;
+ afs_PutCell(c, READ_LOCK);
}
status->Length = linklen;
- afs_PutCell(c, READ_LOCK);
return 1;
}
int afs_SetDynrootEnable(int enable)
{
afs_dynrootEnable = enable;
- return 0;
+ return afs_dynrootCellInit();
}
/*
/*
* Remove a temporary symlink entry from /afs.
*/
-int afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred, char *aname)
+int afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred,
+ char *aname)
{
struct afs_dynSymlink **tpps;
struct afs_dynSymlink *tps;
- struct cell *c;
int found = 0;
if (acred->cr_uid)
}
ReleaseWriteLock(&afs_dynSymlinkLock);
if (found) {
- afs_RefreshDynroot();
+ afs_DynrootInvalidate();
return 0;
}
- /* Check if this is an actual cell? */
- c = afs_FindCellByName(aname, READ_LOCK);
- if (c) {
- afs_PutCell(c, READ_LOCK);
+ if (afs_CellOrAliasExists(aname))
return EROFS;
- } else {
+ else
return ENOENT;
- }
}
/*
char *aname, char *atargetName)
{
struct afs_dynSymlink *tps;
- struct cell *c;
if (acred->cr_uid)
return EPERM;
-
- /* Check if it's already a cell */
- c = afs_FindCellByName(aname, READ_LOCK);
- if (c) {
- afs_PutCell(c, READ_LOCK);
+ if (afs_CellOrAliasExists(aname))
return EEXIST;
- }
/* Check if it's already a symlink */
ObtainWriteLock(&afs_dynSymlinkLock, 91);
afs_dynSymlinkBase = tps;
ReleaseWriteLock(&afs_dynSymlinkLock);
- afs_RefreshDynroot();
+ afs_DynrootInvalidate();
return 0;
}
* WARNING: Data will be written to this file over time by AFS.
*/
-int afs_InitVolumeInfo(register char *afile)
+static int LookupInodeByPath(char *filename, ino_t *inode)
{
afs_int32 code;
- struct osi_file *tfile;
- struct vnode *filevp;
- struct fcache fce;
- AFS_STATCNT(afs_InitVolumeInfo);
#ifdef AFS_LINUX22_ENV
- {
- struct dentry *dp;
- code = gop_lookupname(afile, AFS_UIOSYS, 0, NULL, &dp);
- if (code) return ENOENT;
- fce.inode = volumeInode = dp->d_inode->i_ino;
- dput(dp);
- }
+ struct dentry *dp;
+ code = gop_lookupname(filename, AFS_UIOSYS, 0, NULL, &dp);
+ if (code) return code;
+ *inode = dp->d_inode->i_ino;
+ dput(dp);
#else
- code = gop_lookupname(afile, AFS_UIOSYS, 0, NULL, &filevp);
- if (code) return ENOENT;
- fce.inode = volumeInode = afs_vnodeToInumber(filevp);
+ struct vnode *filevp;
+ code = gop_lookupname(filename, AFS_UIOSYS, 0, NULL, &filevp);
+ if (code) return code;
+ *inode = afs_vnodeToInumber(filevp);
#ifdef AFS_DEC_ENV
grele(filevp);
#else
AFS_RELE((struct vnode *)filevp);
#endif
#endif /* AFS_LINUX22_ENV */
- tfile = afs_CFileOpen(fce.inode);
+
+ return 0;
+}
+
+int afs_InitCellInfo(char *afile)
+{
+ ino_t inode;
+ int code;
+
+ code = LookupInodeByPath(afile, &inode);
+ return afs_cellname_init(inode, code);
+}
+
+int afs_InitVolumeInfo(char *afile)
+{
+ int code;
+ struct osi_file *tfile;
+ struct vnode *filevp;
+
+ AFS_STATCNT(afs_InitVolumeInfo);
+ code = LookupInodeByPath(afile, &volumeInode);
+ if (code) return code;
+ tfile = afs_CFileOpen(volumeInode);
afs_CFileTruncate(tfile, 0);
afs_CFileClose(tfile);
return 0;
AFS_STATCNT(afs_ResourceInit);
RWLOCK_INIT(&afs_xuser, "afs_xuser");
RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
- RWLOCK_INIT(&afs_xcell, "afs_xcell");
RWLOCK_INIT(&afs_xserver, "afs_xserver");
RWLOCK_INIT(&afs_xinterface, "afs_xinterface");
LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
LOCK_INIT(&osi_flplock, "osi_flplock");
RWLOCK_INIT(&afs_xconn, "afs_xconn");
+ afs_CellInit();
afs_InitCBQueue(1); /* initialize callback queues */
if (afs_resourceinit_flag == 0) {
afs_sysname = afs_sysnamelist[0];
strcpy(afs_sysname, SYS_NAME);
afs_sysnamecount = 1;
- QInit(&CellLRU);
#if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
{
if (afs_cold_shutdown) {
afs_resourceinit_flag = 0;
/*
- * Free Cells table allocations
- */
- {
- struct cell *tc;
- register struct afs_q *cq, *tq;
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tc = QTOC(cq); tq = QNext(cq);
- if (tc->cellName)
- afs_osi_Free(tc->cellName, strlen(tc->cellName)+1);
- afs_osi_Free(tc, sizeof(struct cell));
- }
- }
- /*
* Free Volumes table allocations
*/
{
afs_sysname = 0;
afs_sysnamecount = 0;
afs_marinerHost = 0;
- QInit(&CellLRU);
afs_setTimeHost = NULL;
afs_volCounter = 1;
afs_waitForever = afs_waitForeverCount = 0;
- afs_cellindex = 0;
- afs_nextCellNum = 0x100;
afs_FVIndex = -1;
afs_server = (struct rx_service *)0;
RWLOCK_INIT(&afs_xconn, "afs_xconn");
memset((char *)&afs_rootFid, 0, sizeof(struct VenusFid));
RWLOCK_INIT(&afs_xuser, "afs_xuser");
RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
- RWLOCK_INIT(&afs_xcell, "afs_xcell");
RWLOCK_INIT(&afs_xserver, "afs_xserver");
LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
+
+ shutdown_cell();
}
}
-extern int afs_NFSRootOnly;
-int afs_rootCellIndex = 0;
#if !defined(AFS_LINUX20_ENV)
/* This is the common part of the vget VFS call. */
int afs_osi_vget(struct vcache **avcpp, struct fid *afidp,
{
struct VenusFid vfid;
struct SmallFid Sfid;
- extern struct cell *afs_GetCellByIndex();
register struct cell *tcell;
struct vrequest treq;
register afs_int32 code = 0, cellindex;
#ifdef AFS_OSF_ENV
Sfid.Vnode = afidp->fid_reserved;
#endif
- if (afs_NFSRootOnly &&
- Sfid.Volume == afs_rootFid.Fid.Volume &&
- Sfid.Vnode == afs_rootFid.Fid.Vnode &&
- (Sfid.CellAndUnique & 0xffffff) ==
- (afs_rootFid.Fid.Unique & 0xffffff) &&
- ((Sfid.CellAndUnique >> 24) & 0xff) == afs_rootCellIndex) {
- vfid = afs_rootFid;
- }
- else {
- /* Need to extract fid from SmallFid. Will need a wild card option for
- * finding the right vcache entry.
- */
- struct cell *tcell;
- cellindex = (Sfid.CellAndUnique >> 24) & 0xff;
- tcell = afs_GetCellByIndex(cellindex, READ_LOCK, 0 /* don't refresh */);
- if (!tcell) {
- return ENOENT;
- }
- vfid.Cell = tcell->cell;
- afs_PutCell(tcell, WRITE_LOCK);
- vfid.Fid.Volume = Sfid.Volume;
- vfid.Fid.Vnode = Sfid.Vnode;
- vfid.Fid.Unique = Sfid.CellAndUnique & 0xffffff;
- }
+ /* Need to extract fid from SmallFid. Will need a wild card option for
+ * finding the right vcache entry.
+ */
+ cellindex = (Sfid.CellAndUnique >> 24) & 0xff;
+ tcell = afs_GetCellByIndex(cellindex, READ_LOCK);
+ if (!tcell)
+ return ENOENT;
+ vfid.Cell = tcell->cellNum;
+ afs_PutCell(tcell, WRITE_LOCK);
+ vfid.Fid.Volume = Sfid.Volume;
+ vfid.Fid.Vnode = Sfid.Vnode;
+ vfid.Fid.Unique = Sfid.CellAndUnique & 0xffffff;
/* First attempt to find in cache using wildcard. If that fails,
* try the usual route to try to get the vcache from the server.
DECL_PIOCTL(PGetWSCell)
{
- register struct cell *tcell=0, *cellOne=0;
- register struct afs_q *cq, *tq;
+ struct cell *tcell = NULL;
AFS_STATCNT(PGetWSCell);
if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
return EIO; /* Inappropriate ioctl for device */
- ObtainReadLock(&afs_xcell);
- cellOne = NULL;
-
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tcell = QTOC(cq); tq = QNext(cq);
- if (tcell->states & CPrimary) break;
- if (tcell->cell == 1) cellOne = tcell;
- tcell = 0;
- }
- ReleaseReadLock(&afs_xcell);
- if (!tcell) { /* no primary cell, use cell #1 */
- if (!cellOne) return ESRCH;
- tcell = cellOne;
- }
+ tcell = afs_GetPrimaryCell(READ_LOCK);
+ if (!tcell) /* no primary cell? */
+ return ESRCH;
strcpy(aout, tcell->cellName);
*aoutSize = strlen(aout) + 1;
+ afs_PutCell(tcell, READ_LOCK);
return 0;
}
set_parent_pag = 1;
}
tcell = afs_GetCellByName(ain, READ_LOCK);
- if (tcell) {
- i = tcell->cell;
- }
- else {
- goto nocell;
- }
+ if (!tcell) goto nocell;
}
else {
- /* default to cell 1, primary id */
+ /* default to primary cell, primary id */
flag = 1; /* primary id */
- i = 1; /* cell number */
- tcell = afs_GetCell(1, READ_LOCK);
+ tcell = afs_GetPrimaryCell(READ_LOCK);
if (!tcell) goto nocell;
}
+ i = tcell->cellNum;
afs_PutCell(tcell, READ_LOCK);
if (set_parent_pag) {
int pag;
}
}
else {
- if (tu->uid == areq->uid && tu->cell == 1) break;
+ if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
}
}
if (tu) {
else cellp = NULL;
if (!cellp && (temp & 2)) {
/* use local cell */
- cellp = afs_GetCell(1, READ_LOCK);
+ cellp = afs_GetPrimaryCell(READ_LOCK);
}
if (!(temp & 1)) { /* if not fast, call server checker routine */
afs_CheckServers(1, cellp); /* check down servers */
}
linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
- code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0, NULL);
+ code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
+ vlport, (int)0);
return code;
}
DECL_PIOCTL(PNewAlias)
{
/* create a new cell alias */
- register struct cell *tcell;
char *tp = ain;
register afs_int32 code;
char *realName, *aliasName;
- register struct afs_q *cq, *tq;
if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
return EIO; /* Inappropriate ioctl for device */
tp += strlen(aliasName) + 1;
realName = tp;
- /*
- * Prevent user from shooting themselves in the foot -- don't allow
- * creation of aliases when a real cell already exists with that name.
- */
- ObtainReadLock(&afs_xcell);
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tcell = QTOC(cq); tq = QNext(cq);
- if ((afs_strcasecmp(tcell->cellName, aliasName) == 0) &&
- !(tcell->states & CAlias)) {
- ReleaseReadLock(&afs_xcell);
- return EEXIST;
- }
- }
- ReleaseReadLock(&afs_xcell);
-
- code = afs_NewCell(aliasName, 0, CAlias, 0, 0, 0, 0, realName);
+ code = afs_NewCellAlias(aliasName, realName);
*aoutSize = 0;
return code;
}
register struct cell *tcell=0;
register afs_int32 i;
register char *cp, *tp = ain;
- register struct afs_q *cq, *tq;
AFS_STATCNT(PListCells);
if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
memcpy((char *)&whichCell, tp, sizeof(afs_int32));
tp += sizeof(afs_int32);
- tcell = afs_GetRealCellByIndex(whichCell, READ_LOCK, 0);
+ tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
if (tcell) {
cp = aout;
memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
strcpy(cp, tcell->cellName);
cp += strlen(tcell->cellName)+1;
*aoutSize = cp - aout;
+ afs_PutCell(tcell, READ_LOCK);
}
if (tcell) return 0;
else return EDOM;
DECL_PIOCTL(PListAliases)
{
afs_int32 whichAlias;
- register struct cell *tcell=0;
+ register struct cell_alias *tcalias=0;
register char *cp, *tp = ain;
- register struct afs_q *cq, *tq;
if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
return EIO; /* Inappropriate ioctl for device */
memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
tp += sizeof(afs_int32);
- ObtainReadLock(&afs_xcell);
- for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
- tcell = QTOC(cq); tq = QNext(cq);
- if (!(tcell->states & CAlias)) {
- tcell = 0;
- continue;
- }
- if (whichAlias == 0) break;
- tcell = 0;
- whichAlias--;
- }
- if (tcell) {
+ tcalias = afs_GetCellAlias(whichAlias);
+ if (tcalias) {
cp = aout;
- strcpy(cp, tcell->cellName);
- cp += strlen(tcell->cellName)+1;
- strcpy(cp, tcell->realName);
- cp += strlen(tcell->realName)+1;
+ strcpy(cp, tcalias->alias);
+ cp += strlen(tcalias->alias)+1;
+ strcpy(cp, tcalias->cell);
+ cp += strlen(tcalias->cell)+1;
*aoutSize = cp - aout;
+ afs_PutCellAlias(tcalias);
}
- ReleaseReadLock(&afs_xcell);
- if (tcell) return 0;
+ if (tcalias) return 0;
else return EDOM;
}
* l - array of cell ids which have volumes that need to be sorted
* vlonly - sort vl servers or file servers?
*/
-static void ReSortCells(int s, afs_int32 l[], int vlonly)
+static void *ReSortCells_cb(struct cell *cell, void *arg)
+{
+ afs_int32 *p = (afs_int32 *) arg;
+ afs_int32 *l = p + 1;
+ int i, s = p[0];
+
+ for (i=0; i<s; i++) {
+ if (l[i] == cell->cellNum) {
+ ObtainWriteLock(&cell->lock, 690);
+ afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
+ ReleaseWriteLock(&cell->lock);
+ }
+ }
+}
+
+static void ReSortCells(int s, afs_int32 *l, int vlonly)
{
int i;
struct volume *j;
register int k;
if (vlonly) {
- struct cell *tcell;
- ObtainWriteLock(&afs_xcell,300);
- for(k=0;k<s;k++) {
- tcell = afs_GetCellNoLock(l[k], WRITE_LOCK);
- if (!tcell) continue;
- afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
- afs_PutCell(tcell, WRITE_LOCK);
- }
- ReleaseWriteLock(&afs_xcell);
+ afs_int32 *p;
+ p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
+ p[0] = s;
+ memcpy(p+1, l, s * sizeof(afs_int32));
+ afs_TraverseCells(&ReSortCells_cb, p);
+ afs_osi_Free(p, sizeof(afs_int32) * (s+1));
return;
}
if (srvr->cell) {
/* if we don't know yet what cell it's in, this is moot */
- for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
+ for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
/* is it in our list of touched cells ? */ ;
if (j < 0) { /* no, it's not */
- touched[touchedSize++] = srvr->cell->cell;
+ touched[touchedSize++] = srvr->cell->cellNum;
if (touchedSize >= 32) { /* watch for ovrflow */
ReleaseReadLock(&afs_xserver);
ReSortCells(touchedSize, touched, vlonly);
extern void afs_DequeueCallback(struct vcache *avc);
/* afs_cell.c */
-extern struct afs_q CellLRU;
extern afs_rwlock_t afs_xcell;
-extern afs_int32 afs_cellindex;
-extern afs_uint32 afs_nextCellNum;
-extern afs_int32 afs_NewCell(char *acellName, register afs_int32 *acellHosts, int aflags,
- char *linkedcname, u_short fsport, u_short vlport, int timeout, char *aliasFor);
-extern struct cell *afs_GetCell(register afs_int32 acell, afs_int32 locktype);
-extern struct cell *afs_GetCellByIndex(register afs_int32 cellindex,
- afs_int32 locktype, afs_int32 refresh);
-extern struct cell *afs_FindCellByName(register char *acellName, afs_int32 locktype);
-extern struct cell *afs_GetCellByName_Dns(register char *acellName, afs_int32 locktype);
-extern struct cell *afs_GetCellByName(register char *acellName, afs_int32 locktype);
-extern struct cell *afs_GetCellNoLock(register afs_int32 acell, afs_int32 locktype);
-extern void afs_StopAfsdb(void);
-extern int afs_AfsdbHandler(char *acellName, int acellNameLen, afs_int32 *kernelMsg);
-extern int afs_GetCellHostsFromDns(char *acellName, afs_int32 *acellHosts,
- int *timeout, char **realName);
-extern void afs_RefreshCell(register struct cell *ac);
+extern void afs_CellInit(void);
+extern void shutdown_cell(void);
+extern int afs_cellname_init(ino_t inode, int lookupcode);
+extern int afs_cellname_write();
+extern afs_int32 afs_NewCell(char *acellName, afs_int32 *acellHosts,
+ int aflags, char *linkedcname, u_short fsport, u_short vlport,
+ int timeout);
+extern afs_int32 afs_SetPrimaryCell(char *acellName);
+extern struct cell *afs_GetCell(afs_int32 acell, afs_int32 locktype);
+extern struct cell *afs_GetCellStale(afs_int32 acell, afs_int32 locktype);
+extern struct cell *afs_GetCellByIndex(afs_int32 cellidx, afs_int32 locktype);
+extern struct cell *afs_GetCellByName(char *acellName, afs_int32 locktype);
+extern struct cell *afs_GetPrimaryCell(afs_int32 locktype);
+extern int afs_IsPrimaryCellNum(afs_int32 cellnum);
+extern int afs_IsPrimaryCell(struct cell *cell);
+extern void *afs_TraverseCells(void *(*cb)(struct cell *, void *), void *arg);
+extern int afs_CellOrAliasExists(char *aname);
+extern int afs_CellNumValid(afs_int32 cellnum);
+extern afs_int32 afs_NewCellAlias(char *alias, char *cell);
+extern struct cell_alias *afs_GetCellAlias(int index);
+extern int afs_AFSDBHandler(char *acellName, int acellNameLen,
+ afs_int32 *kernelMsg);
+extern void afs_LookupAFSDB(char *acellName);
+extern void afs_StopAFSDB(void);
extern void afs_RemoveCellEntry(struct server *srvp);
-
/* afs_chunk.c */
extern afs_int32 afs_FirstCSize;
extern afs_int32 afs_OtherCSize;
extern int afs_IsDynrootFid(struct VenusFid *fid);
extern void afs_GetDynrootFid(struct VenusFid *fid);
extern int afs_IsDynroot(struct vcache *avc);
-extern void afs_RefreshDynroot(void);
-extern void afs_GetDynroot(char **dynrootDir, int *dynrootLen, struct AFSFetchStatus *status);
+extern void afs_DynrootInvalidate(void);
+extern void afs_GetDynroot(char **dynrootDir, int *dynrootLen,
+ struct AFSFetchStatus *status);
extern void afs_PutDynroot(void);
-extern int afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status);
+extern int afs_DynrootNewVnode(struct vcache *avc,
+ struct AFSFetchStatus *status);
extern int afs_SetDynrootEnable(int enable);
extern int afs_GetDynrootEnable(void);
-extern int afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred, char *aname);
+extern int afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred,
+ char *aname);
extern int afs_DynrootVOPSymlink(struct vcache *avc, struct AFS_UCRED *acred,
- char *aname, char *atargetName);
+ char *aname, char *atargetName);
/* afs_exporter.c */
extern struct afs_exporter *root_exported;
/* afs_util.c */
extern char *afs_cv2string(char *ttp, afs_uint32 aval);
-extern int afs_strcasecmp(register char *s1, register char *s2);
+extern int afs_strcasecmp(char *s1, char *s2);
extern char *afs_strdup(char *s);
extern void print_internet_address(char *preamble, struct srvAddr *sa,
char *postamble, int flag);
+static struct afs_stats_SrvUpDownInfo *
+GetUpDownStats(struct server *srv)
+{
+ struct afs_stats_SrvUpDownInfo *upDownP;
+ u_short fsport = AFS_FSPORT;
+
+ if (srv->cell)
+ fsport = srv->cell->fsport;
+
+ if (srv->addr->sa_portal == fsport)
+ upDownP = afs_stats_cmperf.fs_UpDown;
+ else
+ upDownP = afs_stats_cmperf.vl_UpDown;
+
+ if (srv->cell && afs_IsPrimaryCell(srv->cell))
+ return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
+ else
+ return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
+}
+
/*------------------------------------------------------------------------
* afs_MarkServerUpOrDown
currTimeP = &currTime;
osi_GetuTime(currTimeP);
- if (sa->sa_portal == AFS_FSPORT) {
- upDownP = (a_serverP->cell->cell == 1) ?
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } /*File Server record*/
- else {
- upDownP = (a_serverP->cell->cell == 1) ?
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } /*VL Server record*/
+ upDownP = GetUpDownStats(a_serverP);
if (a_isDown) {
/*
return; /* can't do much */
tc = afs_ConnByHost(aserver, aserver->cell->vlport,
- aserver->cell->cell, areq, 1, SHARED_LOCK);
+ aserver->cell->cellNum, areq, 1, SHARED_LOCK);
if (!tc)
return;
rx_SetConnDeadTime(tc->id, 3);
* in the appropriate places.
*/
srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
- if (currSrvP->addr->sa_portal == AFS_FSPORT) {
- upDownP = (currSrvP->cell->cell == 1) ?
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } /*File Server record*/
- else {
- upDownP = (currSrvP->cell->cell == 1) ?
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]):
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } /*VL Server record*/
-
+ upDownP = GetUpDownStats(currSrvP);
upDownP->sumOfRecordAges += srvRecordAge;
if ((upDownP->ageOfYoungestRecord == 0) ||
(srvRecordAge < upDownP->ageOfYoungestRecord))
continue; /* have just been added by setsprefs */
/* get a connection, even if host is down; bumps conn ref count */
- tu = afs_GetUser(treq.uid, ts->cell->cell, SHARED_LOCK);
- tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cell, tu,
+ tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
+ tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
1/*force*/, 1/*create*/, SHARED_LOCK);
afs_PutUser(tu, SHARED_LOCK);
if (!tc) continue;
*/
if (code == 0 && start == end && afs_setTime != 0 &&
(tc->srvr->server == afs_setTimeHost ||
- /*
- * Sync only to a server in the local cell: cell(id)==1
- * or CPrimary.
- */
+ /* Sync only to a server in the local cell */
(afs_setTimeHost == (struct server *)0 &&
- (ts->cell->cell == 1 || (ts->cell->states&CPrimary))))) {
+ afs_IsPrimaryCell(ts->cell)))) {
char msgbuf[90]; /* strlen("afs: setting clock...") + slop */
/* set the time */
/* With the introduction of this new record, we need to adjust the
* proper individual & global server up/down info.
*/
- if (aport == fsport) { /* File Server record */
- upDownP = (acell == 1) ?
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } else { /* VL Server record */
- upDownP = (acell == 1) ?
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- }
- (upDownP->numTtlRecords) += srvcount;
+ upDownP = GetUpDownStats(newts);
+ upDownP->numTtlRecords += srvcount;
afs_stats_cmperf.srvRecords += srvcount;
if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
currTimeP = &currTime;
osi_GetuTime(currTimeP);
aserver->activationTime = currTime.tv_sec;
- if (sap->sa_portal == AFS_FSPORT) {
- upDownP = (aserver->cell->cell == 1) ?
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
- &(afs_stats_cmperf.fs_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } /*File Server record*/
- else {
- upDownP = (aserver->cell->cell == 1) ?
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_SAME_CELL]) :
- &(afs_stats_cmperf.vl_UpDown[AFS_STATS_UPDOWN_IDX_DIFF_CELL]);
- } /*VL Server record*/
- if (aserver->flags & SRVR_ISDOWN)
- (upDownP->numDownRecords)++;
- else {
- (upDownP->numUpRecords)++;
- (upDownP->numRecordsNeverDown)++;
+ upDownP = GetUpDownStats(aserver);
+ if (aserver->flags & SRVR_ISDOWN) {
+ upDownP->numDownRecords++;
+ } else {
+ upDownP->numUpRecords++;
+ upDownP->numRecordsNeverDown++;
}
}
}
afs_int32 C_afs_MarshallCacheConfig; /* afs_callback.c*/
afs_int32 C_SRXAFSCB_GetCacheConfig; /* afs_callback.c*/
afs_int32 C_SRXAFSCB_GetCE64; /* afs_callback.c*/
+ afs_int32 C_SRXAFSCB_GetCellByNum; /* afs_callback.c*/
};
struct afs_CMMeanStats {
callBacks[0].CallBackType = CB_EXCLUSIVE;
for (safety3 = 0; safety3 < MAXHOSTS*2; safety3++) {
tc = afs_ConnByHost(tsp, tsp->cell->fsport,
- tsp->cell->cell, &treq, 0,
+ tsp->cell->cellNum, &treq, 0,
SHARED_LOCK);
if (tc) {
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
* entries locked.
*/
-int afs_RemoveVCB(register struct VenusFid *afid)
+int afs_RemoveVCB(struct VenusFid *afid)
{
register int i;
register struct server *tsp;
for(i=0;i<NSERVERS;i++) {
for(tsp=afs_servers[i]; tsp; tsp=tsp->next) {
/* if cell is known, and is wrong, then skip this server */
- if (tsp->cell && tsp->cell->cell != afid->Cell) continue;
+ if (tsp->cell && tsp->cell->cellNum != afid->Cell) continue;
/*
* Otherwise, iterate through file IDs we're sending to the
if (flag & DO_STATS) {
if (tvc) afs_stats_cmperf.vcacheHits++;
else afs_stats_cmperf.vcacheMisses++;
- if (afid->Cell == LOCALCELL)
+ if (afs_IsPrimaryCellNum(afid->Cell))
afs_stats_cmperf.vlocalAccesses++;
else
afs_stats_cmperf.vremoteAccesses++;
if (tvc) afs_stats_cmperf.vcacheHits++;
else afs_stats_cmperf.vcacheMisses++;
- if (afid->Cell == LOCALCELL)
+ if (afs_IsPrimaryCellNum(afid->Cell))
afs_stats_cmperf.vlocalAccesses++;
else
afs_stats_cmperf.vremoteAccesses++;
struct volume *afs_UFSGetVolSlot(void)
{
register struct volume *tv, **lv;
- register char *tfile;
+ struct osi_file *tfile;
register afs_int32 i, code;
afs_int32 bestTime;
struct volume *bestVp, **bestLp;
ObtainWriteLock(&afs_xvolume,108);
i = VHash(volid);
for (tv = afs_volumes[i]; tv; tv=tv->next) {
- if (tv->volume == volid && tv->cell == tcell->cell) {
+ if (tv->volume == volid && tv->cell == tcell->cellNum) {
break;
}
}
tv = afs_GetVolSlot();
memset((char *)tv, 0, sizeof(struct volume));
- tv->cell = tcell->cell;
+ tv->cell = tcell->cellNum;
RWLOCK_INIT(&tv->lock, "volume lock");
tv->next = afs_volumes[i]; /* thread into list */
afs_volumes[i] = tv;
tv->volume = volid;
for (j=fvTable[FVHash(tv->cell,volid)]; j!=0; j=tf->next) {
if (afs_FVIndex != j) {
- char *tfile;
+ struct osi_file *tfile;
tfile = osi_UFSOpen(volumeInode);
err = afs_osi_Read(tfile, sizeof(struct fvolume) * j, &staticFVolume, sizeof(struct fvolume));
if (err != sizeof(struct fvolume))
ReleaseWriteLock(&afs_xvolume);
ObtainWriteLock(&tv->lock,111);
if (type == 2) {
- InstallUVolumeEntry(tv, uve, tcell->cell, tcell, areq);
+ InstallUVolumeEntry(tv, uve, tcell->cellNum, tcell, areq);
}
else if (type == 1)
- InstallNVolumeEntry(tv, nve, tcell->cell);
+ InstallNVolumeEntry(tv, nve, tcell->cellNum);
else
- InstallVolumeEntry(tv, ove, tcell->cell);
+ InstallVolumeEntry(tv, ove, tcell->cellNum);
if (agood) {
if (!tv->name) {
tv->name = afs_osi_Alloc(strlen(aname) + 1);
tve.volumeId[ROVOL] = fid->Fid.Volume;
tve.flags = VLF_ROEXISTS;
- tv = afs_SetupVolume(0, bp, &tve, tcell, 0, 0, 0);
+ tv = afs_SetupVolume(0, bp, (char *) &tve, tcell, 0, 0, 0);
afs_PutCell(tcell, READ_LOCK);
return tv;
}
afs_InitReq(&treq, &afs_osi_cred); /* *must* be unauth for vldb */
do {
tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
- tcell->cell, &treq, SHARED_LOCK);
+ tcell->cellNum, &treq, SHARED_LOCK);
if (tconn) {
if (tconn->srvr->server->flags & SNO_LHOSTS) {
type = 0;
memset((char *)&addrs, 0, sizeof(addrs));
do {
tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
- tcell->cell, areq, SHARED_LOCK);
+ tcell->cellNum, areq, SHARED_LOCK);
if (tconn) {
RX_AFS_GUNLOCK();
code = VL_GetAddrsU(tconn->id, &attrs, &uuid, &unique, &nentries, &addrs);
#define AFSLOGFILE "AFSLog"
#define DCACHEFILE "CacheItems"
#define VOLINFOFILE "VolumeItems"
+#define CELLINFOFILE "CellItems"
#define MAXIPADDRS 1024
char confDir[1024]; /*Where the workstation AFS configuration lives*/
char fullpn_DCacheFile[1024]; /*Full pathname of DCACHEFILE*/
char fullpn_VolInfoFile[1024]; /*Full pathname of VOLINFOFILE*/
+char fullpn_CellInfoFile[1024]; /*Full pathanem of CELLINFOFILE*/
char fullpn_AFSLogFile[1024]; /*Full pathname of AFSLOGFILE*/
char fullpn_CacheInfo[1024]; /*Full pathname of CACHEINFO*/
char fullpn_VFile[1024]; /*Full pathname of data cache files*/
char rootVolume[64] = "root.afs"; /*AFS root volume name*/
afs_int32 cacheSetTime = 1; /*Keep checking time to avoid drift?*/
afs_int32 isHomeCell; /*Is current cell info for the home cell?*/
-afs_int32 lookingForHomeCell; /*Are we still looking for the home cell?*/
int createAndTrunc = O_CREAT | O_TRUNC; /*Create & truncate on open*/
int ownerRWmode = 0600; /*Read/write OK by owner*/
static int filesSet = 0; /*True if number of files explicitly set*/
*/
AFSD_INO_T *inode_for_V; /* Array of inodes for desired
* cache files */
-int missing_DCacheFile = 1; /*Is the DCACHEFILE missing?*/
-int missing_VolInfoFile = 1; /*Is the VOLINFOFILE missing?*/
-int afsd_rmtsys = 0; /* Default: don't support rmtsys */
-struct afs_cacheParams cparams; /* params passed to cache manager */
+int missing_DCacheFile = 1; /*Is the DCACHEFILE missing?*/
+int missing_VolInfoFile = 1; /*Is the VOLINFOFILE missing?*/
+int missing_CellInfoFile = 1; /*Is the CELLINFOFILE missing?*/
+int afsd_rmtsys = 0; /* Default: don't support rmtsys */
+struct afs_cacheParams cparams; /* params passed to cache manager */
static int HandleMTab();
return(0);
}
+static void CreateFileIfMissing(char *fullpn, int missing)
+{
+ if (missing) {
+ if (afsd_verbose)
+ printf("CreateFileIfMissing: Creating '%s'\n", fullpn);
+ if (CreateCacheFile(fullpn, NULL))
+ printf("CreateFileIfMissing: Can't create '%s'\n", fullpn);
+ }
+}
+
/*-----------------------------------------------------------------------------
* SweepAFSCache
*
*/
missing_VolInfoFile = 0;
}
+ else if (dirNum < 0 && strcmp(currp->d_name, CELLINFOFILE) == 0) {
+ /*
+ * Found the file holding the cell info.
+ */
+ missing_CellInfoFile = 0;
+ }
else if ((strcmp(currp->d_name, ".") == 0) ||
(strcmp(currp->d_name, "..") == 0) ||
#ifdef AFS_DECOSF_ENV
if (dirNum < 0) {
- /*
+ /*
* Create all the cache files that are missing.
*/
- if (missing_DCacheFile) {
- if (afsd_verbose)
- printf("%s: Creating '%s'\n",
- rn, fullpn_DCacheFile);
- if (CreateCacheFile(fullpn_DCacheFile, NULL))
- printf("%s: Can't create '%s'\n",
- rn, fullpn_DCacheFile);
- }
- if (missing_VolInfoFile) {
- if (afsd_verbose)
- printf("%s: Creating '%s'\n",
- rn, fullpn_VolInfoFile);
- if (CreateCacheFile(fullpn_VolInfoFile, NULL))
- printf("%s: Can't create '%s'\n",
- rn, fullpn_VolInfoFile);
- }
+ CreateFileIfMissing(fullpn_DCacheFile, missing_DCacheFile);
+ CreateFileIfMissing(fullpn_VolInfoFile, missing_VolInfoFile);
+ CreateFileIfMissing(fullpn_CellInfoFile, missing_CellInfoFile);
/* ADJUST CACHE FILES */
char *arock;
struct afsconf_dir *adir; {
register int isHomeCell;
- register int i;
- afs_int32 cellFlags;
+ register int i, code;
+ afs_int32 cellFlags = 0;
afs_int32 hosts[MAXHOSTSPERCELL];
/* figure out if this is the home cell */
isHomeCell = (strcmp(aci->name, LclCellName) == 0);
- if (isHomeCell) {
- lookingForHomeCell = 0;
- cellFlags = 1; /* home cell, suid is ok */
- }
- else {
+ if (!isHomeCell)
cellFlags = 2; /* not home, suid is forbidden */
- }
/* build address list */
for(i=0;i<MAXHOSTSPERCELL;i++)
for upwards compatibility */
/* configure one cell */
- call_syscall(AFSOP_ADDCELL2,
+ code = call_syscall(AFSOP_ADDCELL2,
hosts, /* server addresses */
aci->name, /* cell name */
cellFlags, /* is this the home cell? */
aci->linkedCell); /* Linked cell, if any */
+ if (code)
+ printf("Adding cell '%s': error %d\n", aci->name, code);
return 0;
}
/*
* Set up all the pathnames we'll need for later.
*/
- sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
- sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
+ sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
+ sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
+ sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
sprintf(fullpn_VFile, "%s/", cacheBaseDir);
vFilePtr = fullpn_VFile + strlen(fullpn_VFile);
}
#endif
+ code = call_syscall(AFSOP_BASIC_INIT, 1);
+ if (code)
+ printf("%s: Error %d in basic initialization.\n", rn, code);
+
+ /*
+ * Tell the kernel some basic information about the workstation's cache.
+ */
+ if (afsd_verbose)
+ printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries, %d optimum cache files, %d blocks in the cache, flags = 0x%x, dcache entries %d\n",
+ rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
+ dCacheSize);
+ memset(&cparams, '\0', sizeof(cparams));
+ cparams.cacheScaches = cacheStatEntries;
+ cparams.cacheFiles = cacheFiles;
+ cparams.cacheBlocks = cacheBlocks;
+ cparams.cacheDcaches = dCacheSize;
+ cparams.cacheVolumes = vCacheSize;
+ cparams.chunkSize = chunkSize;
+ cparams.setTimeFlag = cacheSetTime;
+ cparams.memCacheFlag = cacheFlags;
+#ifdef notdef
+ cparams.inodes = inodes;
+#endif
+ call_syscall(AFSOP_CACHEINIT, &cparams);
+ if (afsd_CloseSynch)
+ call_syscall(AFSOP_CLOSEWAIT);
+
+ /*
+ * Sweep the workstation AFS cache directory, remembering the inodes of
+ * valid files and deleting extraneous files. Keep sweeping until we
+ * have the right number of data cache files or we've swept too many
+ * times.
+ *
+ * This also creates files in the cache directory like VolumeItems and
+ * CellItems, and thus must be ran before those are sent to the kernel.
+ */
+ if (afsd_verbose)
+ printf("%s: Sweeping workstation's AFS cache directory.\n",
+ rn);
+ cacheIteration = 0;
+ /* Memory-cache based system doesn't need any of this */
+ if(!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
+ do {
+ cacheIteration++;
+ if (SweepAFSCache(&vFilesFound)) {
+ printf("%s: Error on sweep %d of workstation AFS cache \
+ directory.\n", rn, cacheIteration);
+ exit(1);
+ }
+ if (afsd_verbose)
+ printf("%s: %d out of %d data cache files found in sweep %d.\n",
+ rn, vFilesFound, cacheFiles, cacheIteration);
+ } while ((vFilesFound < cacheFiles) &&
+ (cacheIteration < MAX_CACHE_LOOPS));
+ } else if(afsd_verbose)
+ printf("%s: Using memory cache, not swept\n", rn);
+
+ /*
+ * Pass the kernel the name of the workstation cache file holding the
+ * dcache entries.
+ */
+ if (afsd_debug)
+ printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n",
+ rn, fullpn_DCacheFile);
+ /* once again, meaningless for a memory-based cache. */
+ if(!(cacheFlags & AFSCALL_INIT_MEMCACHE))
+ call_syscall(AFSOP_CACHEINFO, fullpn_DCacheFile);
+
+ /*
+ * Pass the kernel the name of the workstation cache file holding the
+ * cell information.
+ */
+ if (afsd_debug)
+ printf("%s: Calling AFSOP_CELLINFO: cell info file is '%s'\n",
+ rn, fullpn_CellInfoFile);
+ call_syscall(AFSOP_CELLINFO, fullpn_CellInfoFile);
+
if (enable_dynroot) {
if (afsd_verbose)
printf("%s: Enabling dynroot support in kernel.\n", rn);
/*
* Tell the kernel about each cell in the configuration.
*/
- lookingForHomeCell = 1;
-
afsconf_CellApply(cdir, ConfigCell, NULL);
afsconf_CellAliasApply(cdir, ConfigCellAlias, NULL);
/*
- * If we're still looking for the home cell after the whole cell configuration database
- * has been parsed, there's something wrong.
+ * Set the primary cell name.
*/
- if (lookingForHomeCell) {
- printf("%s: Can't find information for home cell '%s' in cell database!\n",
- rn, LclCellName);
- }
+ call_syscall(AFSOP_SET_THISCELL, LclCellName);
/*
* If the root volume has been explicitly set, tell the kernel.
}
/*
- * Tell the kernel some basic information about the workstation's cache.
- */
- if (afsd_verbose)
- printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries, %d optimum cache files, %d blocks in the cache, flags = 0x%x, dcache entries %d\n",
- rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
- dCacheSize);
- memset(&cparams, '\0', sizeof(cparams));
- cparams.cacheScaches = cacheStatEntries;
- cparams.cacheFiles = cacheFiles;
- cparams.cacheBlocks = cacheBlocks;
- cparams.cacheDcaches = dCacheSize;
- cparams.cacheVolumes = vCacheSize;
- cparams.chunkSize = chunkSize;
- cparams.setTimeFlag = cacheSetTime;
- cparams.memCacheFlag = cacheFlags;
-#ifdef notdef
- cparams.inodes = inodes;
-#endif
- call_syscall(AFSOP_CACHEINIT, &cparams);
- if (afsd_CloseSynch)
- call_syscall(AFSOP_CLOSEWAIT);
-
- /*
- * Sweep the workstation AFS cache directory, remembering the inodes of
- * valid files and deleting extraneous files. Keep sweeping until we
- * have the right number of data cache files or we've swept too many
- * times.
- */
- if (afsd_verbose)
- printf("%s: Sweeping workstation's AFS cache directory.\n",
- rn);
- cacheIteration = 0;
- /* Memory-cache based system doesn't need any of this */
- if(!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
- do {
- cacheIteration++;
- if (SweepAFSCache(&vFilesFound)) {
- printf("%s: Error on sweep %d of workstation AFS cache \
- directory.\n", rn, cacheIteration);
- exit(1);
- }
- if (afsd_verbose)
- printf("%s: %d out of %d data cache files found in sweep %d.\n",
- rn, vFilesFound, cacheFiles, cacheIteration);
- } while ((vFilesFound < cacheFiles) &&
- (cacheIteration < MAX_CACHE_LOOPS));
- } else if(afsd_verbose)
- printf("%s: Using memory cache, not swept\n", rn);
-
- /*
- * Pass the kernel the name of the workstation cache file holding the
- * dcache entries.
- */
- if (afsd_debug)
- printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n",
- rn, fullpn_DCacheFile);
- /* once again, meaningless for a memory-based cache. */
- if(!(cacheFlags & AFSCALL_INIT_MEMCACHE))
- call_syscall(AFSOP_CACHEINFO, fullpn_DCacheFile);
-
- /*
* Pass the kernel the name of the workstation cache file holding the
* volume information.
*/
#define AFSOP_SET_DYNROOT 31 /* enable/disable dynroot support */
#define AFSOP_ADDCELLALIAS 32 /* create alias for existing cell */
#define AFSOP_SET_FAKESTAT 33 /* enable/disable fakestat support */
+#define AFSOP_CELLINFO 34 /* set the cellinfo file name */
+#define AFSOP_SET_THISCELL 35 /* set the primary cell */
+#define AFSOP_BASIC_INIT 36 /* used to be part of START_AFS */
/* The range 20-30 is reserved for AFS system offsets in the afs_syscall */
#define AFSCALL_PIOCTL 20
OUT AFSDBCacheEntry64 *ce
) = 65536;
+proc GetCellByNum(
+ IN afs_int32 cellNumber,
+ OUT string cellName<AFSNAMEMAX>,
+ OUT serverList *cellHosts
+) = 65537;
+
return RXGEN_OPCODE;
}
+afs_int32 SRXAFSCB_GetCellByNum(
+ struct rx_call *a_call,
+ afs_int32 a_cellnum,
+ char **a_name,
+ serverList *a_hosts)
+{
+ return RXGEN_OPCODE;
+}
+
/*------------------------------------------------------------------------
* EXPORTED SRXAFSCB_GetLocalCell
*
return 0;
}
-static PrintCacheEntries(aconn, aint32)
-int aint32;
-register struct rx_connection *aconn; {
+struct cell_cache {
+ afs_int32 cellnum;
+ char *cellname;
+ struct cell_cache *next;
+};
+
+static char *GetCellName(struct rx_connection *aconn, afs_int32 cellnum)
+{
+ static int no_getcellbynum;
+ static struct cell_cache *cache;
+ struct cell_cache *tcp;
+ int code;
+ char *cellname;
+ serverList sl;
+
+ if (no_getcellbynum)
+ return NULL;
+
+ for (tcp = cache; tcp; tcp = tcp->next)
+ if (tcp->cellnum == cellnum)
+ return tcp->cellname;
+
+ cellname = NULL;
+ sl.serverList_len = 0;
+ sl.serverList_val = NULL;
+ code = RXAFSCB_GetCellByNum(aconn, cellnum, &cellname, &sl);
+ if (code) {
+ if (code == RXGEN_OPCODE)
+ no_getcellbynum = 1;
+ return NULL;
+ }
+
+ if (sl.serverList_val)
+ free (sl.serverList_val);
+ tcp = malloc(sizeof(struct cell_cache));
+ tcp->next = cache;
+ tcp->cellnum = cellnum;
+ tcp->cellname = cellname;
+ cache = tcp;
+
+ return cellname;
+}
+
+static PrintCacheEntries(struct rx_connection *aconn, int aint32)
+{
register int i;
register afs_int32 code;
struct AFSDBCacheEntry centry;
+ char *cellname;
for(i=0;i<10000;i++) {
code = RXAFSCB_GetCE(aconn, i, ¢ry);
if (!aint32 && !IsLocked(¢ry.lock)) continue;
/* otherwise print this entry */
- printf("** Cache entry @ 0x%08x for %d.%d.%d.%d\n", centry.addr, centry.cell,
- centry.netFid.Volume, centry.netFid.Vnode, centry.netFid.Unique);
+ printf("** Cache entry @ 0x%08x for %d.%d.%d.%d", centry.addr,
+ centry.cell, centry.netFid.Volume, centry.netFid.Vnode,
+ centry.netFid.Unique);
+
+ cellname = GetCellName(aconn, centry.cell);
+ if (cellname)
+ printf(" [%s]\n", cellname);
+ else
+ printf("\n");
+
if (IsLocked(¢ry.lock)) {
printf(" locks: ");
PrintLock(¢ry.lock);
if (Dcells || Dall) {
print_cells(1); /* Handle the afs_cells structures */
+ print_cellaliases(1);
+ print_cellnames(1);
}
if (Dusers || Dall) {
#if !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
int Sum_cellnames=0, Sum_userstp=0, Sum_volnames=0, Sum_exps=0, Sum_nfssysnames=0;
int Sum_vcachemvids=0, Sum_vcachelinkData=0, Sum_vcacheacc=0, Sum_vcachelocks=0;
+int Sum_cellaliases=0, Sum_cellname_names=0;
int print_cells(pnt)
int pnt;
j++;
}
if (pnt) printf("... found %d 'afs_cells' entries\n", j);
+
+ return j;
+}
+
+int print_cellaliases(int pnt)
+{
+ off_t symoff;
+ struct cell_alias *ca, cae;
+ long j = 0;
+
+ if (pnt) printf("\n\nPrinting cell_alias list...\n");
+ findsym( "afs_cellalias_head", &symoff);
+ kread(kmem, symoff, (char *) &ca, sizeof ca);
+ while (ca) {
+ char alias[100], cell[100];
+
+ kread(kmem, (off_t) ca, (char *) &cae, sizeof cae);
+ kread(kmem, (off_t) cae.alias, alias, (KDUMP_SIZE_T)40);
+ alias[40] = '\0';
+ Sum_cellaliases += strlen(alias) + 1;
+ kread(kmem, (off_t) cae.cell, cell, (KDUMP_SIZE_T)40);
+ cell[40] = '\0';
+ Sum_cellaliases += strlen(cell) + 1;
+ if (pnt)
+ printf("%x: alias=%s cell=%s index=%d\n",
+ ca, alias, cell, cae.index);
+ ca = cae.next;
+ j++;
+ }
+ if (pnt) printf("... found %d 'cell_alias' entries\n", j);
+
+ return j;
+}
+
+int print_cellnames(int pnt)
+{
+ off_t symoff;
+ struct cell_name *cn, cne;
+ long j = 0;
+
+ if (pnt) printf("\n\nPrinting cell_name list...\n");
+ findsym( "afs_cellname_head", &symoff);
+ kread(kmem, symoff, (char *) &cn, sizeof cn);
+ while (cn) {
+ char cellname[100];
+
+ kread(kmem, (off_t) cn, (char *) &cne, sizeof cne);
+ kread(kmem, (off_t) cne.cellname, cellname, (KDUMP_SIZE_T)40);
+ cellname[40] = '\0';
+ Sum_cellname_names += strlen(cellname) + 1;
+ if (pnt)
+ printf("%x: cellnum=%d cellname=%s used=%d\n",
+ cn, cne.cellnum, cellname, cne.used);
+ cn = cne.next;
+ j++;
+ }
+ if (pnt) printf("... found %d 'cell_name' entries\n", j);
+
return j;
}
T += j;
printf("%20s:\t%8d bytes\t[%d cells/%d bytes each + %d bytes for cell names]\n", "Cell package", j, i, sizeof(struct cell), Sum_cellnames);
+ Sum_cellaliases=0;
+ i = print_cellaliases(0);
+ j = (i * sizeof(struct cell_alias)) + Sum_cellaliases;
+ T += j;
+ printf("%20s:\t%8d bytes\t[%d cell_aliases/%d bytes each + %d bytes for cell names]\n", "Cell package", j, i, sizeof(struct cell_alias), Sum_cellaliases);
+
+ Sum_cellname_names=0;
+ i = print_cellnames(0);
+ j = (i * sizeof(struct cell_name)) + Sum_cellname_names;
+ T += j;
+ printf("%20s:\t%8d bytes\t[%d cell_names/%d bytes each + %d bytes for cell name strings]\n", "Cell package", j, i, sizeof(struct cell_name), Sum_cellname_names);
+
Sum_userstp=0;
i = print_users(0);
j = (i * sizeof(struct unixuser)) + Sum_userstp;
cellName[40] = 0;
Sum_cellnames += strlen(cellName)+1;
if (pnt) {
- printf("%lx: cell=%s, cellname=%s, states=%x, cindex=%d fsport=%d vlport=%d timeout=%d\n", ptr,
- PrintIPAddr(clep->cell), cellName, clep->states, clep->cellIndex,
- clep->fsport, clep->vlport, clep->timeout);
+ printf("%lx: cellname=%s, states=%x, cnum=%d, cindex=%d fsport=%d vlport=%d timeout=%d cnamep=%x\n", ptr,
+ cellName, clep->states, clep->cellNum, clep->cellIndex,
+ clep->fsport, clep->vlport, clep->timeout, clep->cnamep);
#ifdef AFS33
if (clep->lcellp)
printf("\tlinked cellp %lx\n", clep->lcellp);
}
+afs_int32 SRXAFSCB_GetCellByNum(
+ struct rx_call *a_call,
+ afs_int32 a_cellnum,
+ char **a_name,
+ serverList *a_hosts)
+{
+ return RXGEN_OPCODE;
+}
+
+
/*------------------------------------------------------------------------
* EXPORTED SRXAFSCB_GetLocalCell
*