]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE12-new-and-maybe-improved-cell-code-20020822
authorNickolai Zeldovich <kolya@mit.edu>
Thu, 6 Mar 2003 15:25:35 +0000 (15:25 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 6 Mar 2003 15:25:35 +0000 (15:25 +0000)
This is mostly a rewrite of src/afs/afs_cell.c, and associated changes
to other things.  Features of the new cell code:

 * Persistent name-to-cell-number mapping across reboots, to ensure the
   cell numbers in the dcache are meaningful.  Stored in the new cache
   file, /usr/vice/cache/CellInfo.
 * Allow cmdebug to query the cell number to cell name mapping.
 * Allow clients to have an empty CellServDB as long as AFSDB is enabled
   and ThisCell has AFSDB records.
 * The home cell retains the setuid bit even if looked up via AFSDB.
 * Dynroot gets its own cell, rather than piggybacking on cell 1.
 * Cell 1 is no longer special; cell numbers are now semi-opaque.
 * Convert cell traversal code to using GetCellByIndex rather than
   directly poking at CellLRU / afs_xcell.
 * Separate cells from aliases, which shouldn't have been the same
   in the first place.
 * Cleaner code (IMHO).

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================

correct a code block so patch is correct

(cherry picked from commit 629d0806549d5b9cff9cd6f8eae50cf11c3e85ac)

26 files changed:
src/afs/IRIX/osi_vfsops.c
src/afs/VNOPS/afs_vnop_lookup.c
src/afs/afs.h
src/afs/afs_analyze.c
src/afs/afs_call.c
src/afs/afs_callback.c
src/afs/afs_cell.c
src/afs/afs_daemons.c
src/afs/afs_dcache.c
src/afs/afs_dynroot.c
src/afs/afs_init.c
src/afs/afs_osi_vget.c
src/afs/afs_pioctl.c
src/afs/afs_prototypes.h
src/afs/afs_server.c
src/afs/afs_stats.h
src/afs/afs_vcache.c
src/afs/afs_volume.c
src/afsd/afsd.c
src/config/afs_args.h
src/fsint/afscbint.xg
src/fsprobe/fsprobe_callback.c
src/venus/cmdebug.c
src/venus/kdump.c
src/vol/vnode.c
src/xstat/xstat_fs_callback.c

index e93fe01bbe871aff7fc9a933dc8029cccb65954d..87c15cfdf7b1459eb3173143e229dc965cc49858 100644 (file)
@@ -518,7 +518,6 @@ afs_vget(OSI_VFS_DECL(afsp), vnode_t **avcp, struct fid *fidp)
 {
     struct VenusFid vfid;
     struct vrequest treq;
-    extern struct cell *afs_GetCellByIndex();
     register struct cell *tcell;
     register afs_int32 code = 0;
     afs_int32 ret;
@@ -537,13 +536,13 @@ afs_vget(OSI_VFS_DECL(afsp), vnode_t **avcp, struct fid *fidp)
     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;
index 67faf8bf085a8bc7d2c9fcfc9d60a2ed3d355ea3..50fe768f1cd10194dfdb54bfacc4d6719276b614 100644 (file)
@@ -137,10 +137,10 @@ EvalMountPoint(avc, advc, avolpp, areq)
     }
     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);         
 
@@ -255,6 +255,9 @@ void
 afs_InitFakeStat(state)
     struct afs_fakestat_state *state;
 {
+    if (!afs_fakestat_enable)
+       return;
+
     state->valid = 1;
     state->did_eval = 0;
     state->need_release = 0;
@@ -275,11 +278,13 @@ int afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
     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;
@@ -396,6 +401,9 @@ void
 afs_PutFakeStat(state)
     struct afs_fakestat_state *state;
 {
+    if (!afs_fakestat_enable)
+       return;
+
     osi_Assert(state->valid == 1);
     if (state->need_release)
        afs_PutVCache(state->root_vp, 0);
@@ -1313,20 +1321,14 @@ afs_lookup(adp, aname, avcp, acred)
     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);
     }
index d3ff50343befb2109c79a0fe6cbd2663bf933c67..8f93de5c4fe42ee040454e9e0b71603a9d8616a7 100644 (file)
@@ -181,29 +181,43 @@ struct afs_cbr {
     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)
@@ -992,7 +1006,6 @@ extern struct volume           *afs_GetVolumeByName();
 extern struct conn         *afs_Conn();
 extern struct conn         *afs_ConnByHost();
 extern struct conn         *afs_ConnByMHosts();
-extern afs_int32                   afs_NewCell();
 extern struct dcache       *afs_GetDCache();
 extern struct dcache       *afs_FindDCache();
 extern struct dcache       *afs_NewDCache();
index 90540117bf64ba9dd59e48b51aea92f9de47dc36..06f7d4c790ced4c6e4a1e5bd5abdaf95d95e7e4d 100644 (file)
@@ -179,7 +179,7 @@ static int VLDB_Same (afid, areq)
     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;
@@ -392,8 +392,8 @@ int afs_Analyze(aconn, acode, afid, areq, op, locktype, cellp)
            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);
@@ -492,7 +492,7 @@ int afs_Analyze(aconn, acode, afid, areq, op, locktype, cellp)
        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", 
index 47bee60c3e1037b1686b2bd3d1f2438f1b8849a2..2fd484bf65ce4be9436b108f418bee1e0071f2e0 100644 (file)
@@ -83,6 +83,7 @@ static int afs_CacheInit_Done = 0;
 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);
@@ -99,6 +100,9 @@ static int afs_InitSetup(int preallocs)
     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
@@ -121,6 +125,9 @@ static int afs_InitSetup(int preallocs)
     /* resource init creates the services */
     afs_ResourceInit(preallocs);
 
+    afs_InitSetup_done = 1;
+    afs_osi_Wakeup(&afs_InitSetup_done);
+
     return code;
 }
 #if defined(AFS_LINUX24_ENV) && defined(COMPLETION_H_EXISTS)
@@ -294,6 +301,11 @@ afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
 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
@@ -377,21 +389,11 @@ long parm, parm2, parm3, parm4, parm5, parm6;
 #endif
     else if (parm == AFSOP_START_AFS) {
        /* afs daemon */
-       afs_int32 temp;
-
        if (AFS_Running) goto out;
        AFS_Running = 1;
        while (afs_initState < AFSOP_START_AFS) 
            afs_osi_Sleep(&afs_initState);
 
-#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 */
-       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 */
-#endif
-       DInit(temp);
        afs_initState = AFSOP_START_BKG;
        afs_osi_Wakeup(&afs_initState);
        afs_osi_Invisible();
@@ -452,13 +454,31 @@ long parm, parm2, parm3, parm4, parm5, parm6;
     }
 #endif 
 #endif
+    else if (parm == AFSOP_BASIC_INIT) {
+       afs_int32 temp;
+
+       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
+       /* 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; /* though we really should have this many */
+#endif
+       DInit(temp);
+       afs_rootFid.Fid.Volume = 0;
+       code = 0;
+    }
     else if (parm == AFSOP_ADDCELL) {
        /* add a cell.  Parameter 2 is 8 hosts (in net order),  parm 3 is the null-terminated
         name.  Parameter 4 is the length of the name, including the null.  Parm 5 is the
         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)) 
@@ -467,18 +487,13 @@ long parm, parm2, parm3, parm4, parm5, parm6;
                AFS_COPYIN((char *)parm3, tcell.cellName, parm4, code);
                if (!code) 
                    afs_NewCell(tcell.cellName, tcell.hosts, parm5,
-                               (char *)0, (u_short)0, (u_short)0, (int)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 */
@@ -497,7 +512,7 @@ long parm, parm2, parm3, parm4, parm5, parm6;
                }
                if (!code)
                    afs_NewCell(tbuffer1, tcell.hosts, cflags, 
-                               lcnamep, (u_short)0, (u_short)0, (int)0);
+                               lcnamep, 0, 0, 0);
            }
        }
        osi_FreeSmallSpace(tbuffer);
@@ -509,34 +524,33 @@ long parm, parm2, parm3, parm4, parm5, parm6;
         * 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 */
-                              (char *) 0,      /* 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)
@@ -585,12 +599,6 @@ long parm, parm2, parm3, parm4, parm5, parm6;
        code = afs_InitCacheFile((char *) 0, 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);
 
@@ -600,29 +608,31 @@ long parm, parm2, parm3, parm4, parm5, parm6;
        }
        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);
     }
@@ -827,7 +837,7 @@ long parm, parm2, parm3, parm4, parm5, parm6;
        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;
@@ -1451,7 +1461,7 @@ afs_shutdown()
     }
 #ifdef AFS_AFSDB_ENV
     afs_warn("AFSDB... ");
-    afs_StopAfsdb();
+    afs_StopAFSDB();
     while (afs_termState == AFSOP_STOP_AFSDB)
        afs_osi_Sleep(&afs_termState);
 #endif
index fe6ccf79c2f8c985001100724ae25dc296c3d448..55639ea6065d41befd4c2f5e9756450af0ddf29c 100644 (file)
@@ -1137,7 +1137,7 @@ int SRXAFSCB_GetCellServDB(
 #endif /* RX_ENABLE_LOCKS */
     AFS_STATCNT(SRXAFSCB_GetCellServDB);
 
-    tcell = afs_GetCellByIndex(a_index, READ_LOCK, 0);
+    tcell = afs_GetCellByIndex(a_index, READ_LOCK);
 
     if (!tcell) {
       i = 0;
@@ -1203,7 +1203,6 @@ int SRXAFSCB_GetLocalCell(
 {
     int plen;
     struct cell *tcell;
-    struct afs_q *cq, *tq;
     char *t_name, *p_name = NULL;
 
 #ifdef RX_ENABLE_LOCKS
@@ -1214,27 +1213,16 @@ int SRXAFSCB_GetLocalCell(
     /* 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);
 #ifdef RX_ENABLE_LOCKS
        AFS_GUNLOCK();
 #endif /* RX_ENABLE_LOCKS */
@@ -1245,13 +1233,12 @@ int SRXAFSCB_GetLocalCell(
     if (p_name)
        memcpy(t_name, p_name, plen);
 
-    ReleaseReadLock(&afs_xcell);
-
 #ifdef RX_ENABLE_LOCKS
     AFS_GUNLOCK();
 #endif /* RX_ENABLE_LOCKS */
 
     *a_name = t_name;
+    if (tcell) afs_PutCell(tcell, READ_LOCK);
     return 0;
 }
 
@@ -1369,3 +1356,63 @@ int SRXAFSCB_GetCacheConfig(
 
     return 0;
 }
+
+/*------------------------------------------------------------------------
+ * 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;
+}
index e00e6548e5c590c5d21612a13724c062517a1530..8f2ee0ecd22056595662f75b4bfc9ecdf5fd067d 100644 (file)
  * Implements:
  */
 #include <afsconfig.h>
-#include "../afs/param.h"
+#include "afs/param.h"
 
 RCSID("$Header$");
 
-#include "../afs/stds.h"
-#include "../afs/sysincludes.h"        /* Standard vendor system headers */
-
-#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/stds.h"
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afsincludes.h"       /* Afs-based standard headers */
+#include "afs/afs_stats.h"   /* afs statistics */
+#include "afs/afs_osi.h"
 
 /* Local variables. */
-struct cell *afs_rootcell = 0;
-
-/* Handler waiting for request from client */
-static char afs_AfsdbHandlerWait;
-/* Client waiting for handler to become available or finish request */
-static char 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;
-
-
-struct cell *afs_GetCellByName2();
-
-int afs_strcasecmp(s1, s2)
-    register char *s1, *s2;
-{
-    while (*s1 && *s2) {
-       register char c1, c2;
-
-       c1 = *s1++;
-       c2 = *s2++;
-       if (c1 >= 'A' && c1 <= 'Z') c1 += 0x20;
-       if (c2 >= 'A' && c2 <= 'Z') c2 += 0x20;
-       if (c1 != c2)
-           return c1-c2;
-    }
-
-    return *s1 - *s2;
-}
+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()
+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(acellName, acellNameLen, kernelMsg)
-    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
 
+static int afs_GetCellHostsAFSDB(char *acellName, afs_int32 *acellHosts,
+       int *timeout, char **realName)
+{
+    AFS_ASSERT_GLOCK();
+    if (!afsdb_handler_running) return ENOENT;
+
+    ObtainWriteLock(&afsdb_client_lock, 685);
+    ObtainWriteLock(&afsdb_req.lock, 686);
 
-int afs_GetCellHostsFromDns(acellName, acellHosts, timeout, realName)
-    char *acellName;
-    afs_int32 *acellHosts;
-    int *timeout;
-    char **realName;
+    *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
+
+void afs_LookupAFSDB(char *acellName)
 {
 #ifdef AFS_AFSDB_ENV
-    char grab_glock = 0;
+    afs_int32 cellHosts[MAXCELLHOSTS];
+    char *realName = NULL;
+    int code, timeout;
+    
+    code = afs_GetCellHostsAFSDB(acellName, cellHosts, &timeout, &realName);
+    if (code) goto done;
+    code = afs_NewCell(realName, cellHosts, CNoSUID, NULL, 0, 0, timeout);
+    if (code) goto done;
 
-    if (!afs_AfsdbHandlerPresent) return ENOENT;
+    /* If we found an alias, create it */
+    if (afs_strcasecmp(acellName, realName))
+       afs_NewCellAlias(acellName, realName);
 
-    /* Initialize host list to empty in case the handler is gone */
-    *acellHosts = 0;
+done:
+    if (realName)
+       afs_osi_FreeStr(realName);
+#endif
+}
 
-    if (!ISAFS_GLOCK()) {
-       grab_glock = 1;
-       AFS_GLOCK();
-    }
+/*
+ * 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
+ */
 
-    /* Wait until the AFSDB handler is available, and grab it */
-    while (afs_AfsdbHandlerInuse)
-       afs_osi_Sleep(&afs_AfsdbLookupWait);
-    afs_AfsdbHandlerInuse = 1;
+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;
 
-    /* Set up parameters for the handler */
-    afs_AfsdbHandler_CellName = acellName;
-    afs_AfsdbHandler_CellHosts = acellHosts;
-    afs_AfsdbHandler_Timeout = timeout;
-    afs_AfsdbHandler_RealName = realName;
+static struct cell_name *afs_cellname_new(char *name, afs_int32 cellnum)
+{
+    struct cell_name *cn;
 
-    /* Wake up the AFSDB handler */
-    afs_AfsdbHandler_Completed = 0;
-    afs_AfsdbHandler_ReqPending = 1;
-    afs_osi_Wakeup(&afs_AfsdbHandlerWait);
+    if (cellnum == 0)
+       cellnum = 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);
+    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;
 
-    /* Release the AFSDB handler and wake up others waiting for it */
-    afs_AfsdbHandlerInuse = 0;
-    afs_osi_Wakeup(&afs_AfsdbLookupWait);
+    if (cellnum >= afs_cellnum_next)
+       afs_cellnum_next = cellnum + 1;
 
-    if (grab_glock) AFS_GUNLOCK();
+    return cn;
+}
 
-    if (*acellHosts) return 0;
-    return ENOENT;
-#else
-    return ENOENT;
-#endif
+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;
+
+    return NULL;
 }
 
+static struct cell_name *afs_cellname_lookup_name(char *name)
+{
+    struct cell_name *cn;
+
+    for (cn = afs_cellname_head; cn; cn = cn->next)
+       if (strcmp(cn->cellname, name) == 0)
+           return cn;
 
-void afs_RefreshCell(ac)
-    register struct cell *ac;
+    return NULL;
+}
+
+static void afs_cellname_ref(struct cell_name *cn)
 {
-    afs_int32 cellHosts[MAXCELLHOSTS];
-    char *realName = NULL;
-    struct cell *tc;
-    int timeout;
-
-    /* Don't need to do anything if no timeout or it's not expired */
-    if (!ac->timeout || ac->timeout > osi_Time()) 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, (char *) 0, 0, 0, timeout, (char *) 0);
-
-    /* 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_GetCellByName2(realName, READ_LOCK, 0 /* no AFSDB */);
-
-       if (tc) {
-           afs_NewCell(ac->cellName, 0, CAlias, (char *) 0, 0, 0,
-                       timeout, tc->cellName);
-           afs_PutCell(tc, READ_LOCK);
+    if (!cn->used) {
+       cn->used = 1;
+       afs_cellname_dirty = 1;
+    }
+}
+
+int afs_cellname_init(ino_t inode, int lookupcode)
+{
+    struct osi_file *tfile;
+    int cc, off = 0;
+
+    ObtainWriteLock(&afs_xcell, 692);
+
+    afs_cellnum_next = 1;
+    afs_cellname_dirty = 0;
+
+    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';
+
+       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);
     }
 
-done:
-    if (realName)
-       afs_osi_Free(realName, strlen(realName) + 1);
+    osi_UFSClose(tfile);
+    ReleaseWriteLock(&afs_xcell);
+    return 0;
 }
 
-
-struct cell *afs_GetCellByName_Dns(acellName, locktype)
-    register char *acellName;
-    afs_int32 locktype;
+int afs_cellname_write()
 {
-    afs_int32 cellHosts[MAXCELLHOSTS];
-    char *realName = NULL;
-    struct cell *tc;
-    int timeout;
+    struct osi_file *tfile;
+    struct cell_name *cn;
+    int 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;
+    }
 
-    if (afs_GetCellHostsFromDns(acellName, cellHosts, &timeout, &realName))
-       goto bad;
-    if (afs_NewCell(realName, cellHosts, CNoSUID, (char *) 0, 0, 0,
-                   timeout, (char *) 0))
-       goto bad;
+    for (cn = afs_cellname_head; cn; cn = cn->next) {
+       afs_int32 magic, cellnum, clen;
+       int cc;
 
-    /* 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_GetCellByName2(realName, READ_LOCK, 0 /* no AFSDB */);
-       if (!tc)
-           goto bad;
+       if (!cn->used)
+           continue;
 
-       if (afs_NewCell(acellName, 0, CAlias, (char *) 0, 0, 0,
-                       timeout, tc->cellName)) {
-           afs_PutCell(tc, READ_LOCK);
-           goto bad;
-       }
+       magic = AFS_CELLINFO_MAGIC;
+       cc = afs_osi_Write(tfile, off, &magic, sizeof(magic));
+       if (cc != sizeof(magic))
+           break;
+       off += cc;
 
-       afs_PutCell(tc, READ_LOCK);
+       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;
     }
 
-    if (realName)
-       afs_osi_Free(realName, strlen(realName) + 1);
-    return afs_GetCellByName2(acellName, locktype, 0);
+    osi_UFSClose(tfile);
+    ReleaseWriteLock(&afs_xcell);
+    return 0;
+}
 
-bad:
-    if (realName)
-       afs_osi_Free(realName, strlen(realName) + 1);
-    return (struct cell *) 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_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)
+{
+    struct cell_alias *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;
 
-struct cell *afs_GetCellByName2(acellName, locktype, trydns)
-    register char *acellName;
-    afs_int32 locktype;
-    char trydns;
+    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)
 {
-    register struct cell *tc;
-    register struct afs_q *cq, *tq;
-    int didAlias = 0;
+    return;
+}
 
-    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 (struct cell *) 0;
-               didAlias = 1;
-               goto retry;
-           }
-           return tc;
-       }
+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 trydns ? afs_GetCellByName_Dns(acellName, locktype)
-                 : (struct cell *) 0;
 
-} /*afs_GetCellByName2*/
+    afs_DynrootInvalidate();
+    return 0;
+}
 
+/*
+ * 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 cell *afs_GetCellByName(acellName, locktype)
-    register char *acellName;
-    afs_int32 locktype;
+struct afs_q CellLRU;          /* Export for kdump */
+static char *afs_thiscell;
+static afs_int32 afs_cellindex;
+
+static void afs_UpdateCellLRU(struct cell *c)
 {
-    return afs_GetCellByName2(acellName, locktype, 1);
+    ObtainWriteLock(&afs_xcell, 100);
+    QRemove(&c->lruq);
+    QAdd(&CellLRU, &c->lruq);
+    ReleaseWriteLock(&afs_xcell);
+}
 
-} /*afs_GetCellByName*/
+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(acell, locktype, holdxcell)
-    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 (struct cell *) 0;
 
-} /*afs_GetCell*/
+    return ret;
+}
+
+void *afs_TraverseCells(void *(*cb)(struct cell *, void *), void *arg)
+{
+    void *ret;
+
+    ObtainReadLock(&afs_xcell);
+    ret = afs_TraverseCells_nl(cb, arg);
+    ReleaseReadLock(&afs_xcell);
+
+    return ret;
+}
 
-struct cell *afs_GetCell(acell, locktype)
-    register afs_int32 acell;
-    afs_int32 locktype;
+static void *afs_choose_cell_by_name(struct cell *cell, void *arg)
 {
-    return afs_GetCellInternal(acell, locktype, 1);
+    return strcmp(cell->cellName, (char *) arg) ? NULL : cell;
 }
 
-/* This is only to be called if the caller is already holding afs_xcell */
-struct cell *afs_GetCellNoLock(acell, locktype)
-    register afs_int32 acell;
-    afs_int32 locktype;
+static void *afs_choose_cell_by_num(struct cell *cell, void *arg)
 {
-    return afs_GetCellInternal(acell, locktype, 0);
+    return (cell->cellNum == *((afs_int32 *) arg)) ? cell : NULL;
 }
 
-struct cell *afs_GetCellByIndex(cellindex, locktype, refresh)
-    register afs_int32 cellindex;
-    afs_int32 locktype;
-    afs_int32 refresh;
+static void *afs_choose_cell_by_index(struct cell *cell, void *arg)
 {
-    register struct cell *tc;
-    register struct afs_q *cq, *tq;
+    return (cell->cellIndex == *((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 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);
     }
-    ReleaseWriteLock(&afs_xcell);
-    return (struct cell *) 0;
+    if (tc) {
+       afs_cellname_ref(tc->cnamep);
+       afs_UpdateCellLRU(tc);
+       afs_RefreshCell(tc);
+    }
+
+    return tc;
+}
 
-} /*afs_GetCellByIndex*/
+struct cell *afs_GetCell(afs_int32 cellnum, afs_int32 locktype)
+{
+    struct cell *tc;
+    struct cell_name *cn;
 
+    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_GetRealCellByIndex(cellindex, locktype, refresh)
-    register afs_int32 cellindex;
-    afs_int32 locktype;
-    afs_int32 refresh;
+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 (struct cell *) 0;
-} /*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(acellName, acellHosts, aflags, linkedcname, fsport, vlport, timeout, aliasFor)
-    int aflags;
-    char *acellName;
-    register afs_int32 *acellHosts;
-    char *linkedcname;
-    u_short fsport, 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);
-    if (!(aflags & CAlias) && *acellHosts == 0)
-       /* need >= one host to gen cell # */
-       return EINVAL;
+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. */
-           if (timeout && !tc->timeout) {
-               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 = (struct cell *)0;
-       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;
@@ -542,71 +693,154 @@ afs_int32 afs_NewCell(acellName, acellHosts, aflags, linkedcname, fsport, vlport
     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;
+}
 
-} /*afs_NewCell*/
+/*
+ * 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)
+ */
 
-afs_RemoveCellEntry(struct server *srvp)
+void afs_CellInit()
 {
-  struct cell *tc;
-  afs_int32 j, k;
+    RWLOCK_INIT(&afs_xcell, "afs_xcell");
+#ifdef AFS_AFSDB_ENV
+    RWLOCK_INIT(&afsdb_req.lock, "afsdb_req.lock");
+#endif
+    QInit(&CellLRU);
 
-  tc = srvp->cell;
-  if (!tc) return;
+    afs_cellindex = 0;
+    afs_cellalias_index = 0;
+}
 
-  /* 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);
+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(&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;
+    }
+}
index 5f0d4ea09659fb4b80b722684aadb383918712b8..89cc4987775877da11d85bb2ba9ab9bd57a19e06 100644 (file)
@@ -265,57 +265,67 @@ void afs_Daemon() {
     }
 }
 
-afs_CheckRootVolume () {
+int afs_CheckRootVolume (void) {
     char rootVolName[32];
-    register struct volume *tvp;
+    struct volume *tvp;
     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, (struct vrequest *) 0, READ_LOCK);
+        afs_GetDynrootFid(&afs_rootFid);
+        tvp = afs_GetVolume(&afs_rootFid, NULL, READ_LOCK);
     } else {
-       tvp = afs_GetVolumeByName(rootVolName, LOCALCELL, 1, (struct vrequest *) 0, READ_LOCK);
+        tvp = afs_GetVolumeByName(rootVolName, localcell, 1, NULL, READ_LOCK);
     }
-    if (!tvp) {
-       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, (struct vrequest *) 0, READ_LOCK);
-       }
+    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);
+        }
     }
     if (tvp) {
-       if (!usingDynroot) {
-           int volid = (tvp->roVol? tvp->roVol : tvp->volume);
-           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
-                * the afs_globalVp so that it will be reevaluated.
-                * Just decrement the reference count. This only occurs during
-                * initial cell setup and can panic the machine if we set the
-                * count to zero and fs checkv is executed when the current
-                * directory is /afs.
-                */
-               AFS_FAST_RELE(afs_globalVp);
-               afs_globalVp = 0;
-           }
-           afs_rootFid.Fid.Volume = volid;
-           afs_rootFid.Fid.Vnode = 1;
-           afs_rootFid.Fid.Unique = 1;
-       }
-       afs_initState = 300;    /* won */
-       afs_osi_Wakeup(&afs_initState);
-       afs_PutVolume(tvp, READ_LOCK);
+        if (!usingDynroot) {
+            int volid = (tvp->roVol? tvp->roVol : tvp->volume);
+            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
+              * the afs_globalVp so that it will be reevaluated.
+              * Just decrement the reference count. This only occurs during
+              * initial cell setup and can panic the machine if we set the
+              * count to zero and fs checkv is executed when the current
+              * directory is /afs.
+              */
+                AFS_FAST_RELE(afs_globalVp);
+                afs_globalVp = 0;
+            }
+            afs_rootFid.Fid.Volume = volid;
+            afs_rootFid.Fid.Vnode = 1;
+            afs_rootFid.Fid.Unique = 1;
+        }
+        afs_initState = 300;    /* won */
+        afs_osi_Wakeup(&afs_initState);
+        afs_PutVolume(tvp, READ_LOCK);
     }
 #ifdef AFS_DEC_ENV
 /* This is to make sure that we update the root gnode */
index 51fbf981e3fde3ac064a5793cf0672ab4ecf8b25..df908d2bfa2736b95ba6f6e899facf737dcad2fe 100644 (file)
@@ -2128,7 +2128,7 @@ done:
     /*
      * 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++;
@@ -2297,6 +2297,7 @@ struct dcache *afs_UFSGetDSlot(aslot, tmpdc)
 
     register afs_int32 code;
     register struct dcache *tdc;
+    int entryok;
 
     AFS_STATCNT(afs_UFSGetDSlot);
     if (CheckLock(&afs_xdcache) != -1) osi_Panic("getdslot nolock");
@@ -2345,9 +2346,16 @@ struct dcache *afs_UFSGetDSlot(aslot, tmpdc)
     /*
       * 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;
@@ -2406,8 +2414,10 @@ afs_WriteDCache(adc, atime)
     /*
      * 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;
 
index 107b3a8bd3810adee82b4e1c02a0e19a539ffadf..7241166258dc7ae6265fecf384016e2f188cd712 100644 (file)
@@ -14,7 +14,7 @@
  * afs_IsDynrootFid
  * afs_GetDynrootFid
  * afs_IsDynroot
- * afs_RefreshDynroot
+ * afs_DynrootInvalidate
  * afs_GetDynroot
  * afs_PutDynroot
  * afs_DynrootNewVnode
@@ -38,7 +38,7 @@
 #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
@@ -48,7 +48,8 @@
  * 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 */
@@ -89,6 +94,30 @@ static int afs_dynSymlinkIndex = 0;
 extern afs_int32 afs_cellindex;
 extern afs_rwlock_t afs_xvcache;
 
+/*
+ * 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.
  */
@@ -97,7 +126,7 @@ 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);
@@ -109,7 +138,7 @@ afs_IsDynrootFid(struct VenusFid *fid)
 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;
@@ -213,32 +242,61 @@ afs_dynroot_addDirEnt(dirHeader, curPageP, curChunkP, name, vnode)
     *curChunkP = curChunk;
 }
 
+/*
+ * 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, 0, 0, &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()
+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, dotLen;
     char *newDir, *dotCell;
     struct DirHeader *dirHeader;
-    struct PageHeader *pageHeader;
     struct DirEntry *dirEntry;
-    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
@@ -249,9 +307,10 @@ afs_RefreshDynroot()
     /* 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) {
@@ -274,6 +333,32 @@ afs_RefreshDynroot()
        afs_osi_Free(dotCell, dotLen);
        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;
@@ -317,8 +402,9 @@ afs_RefreshDynroot()
     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;
 
        dotLen = strlen(c->cellName) + 2;
        dotCell = afs_osi_Alloc(dotLen);
@@ -329,12 +415,26 @@ afs_RefreshDynroot()
        afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
                              dotCell, VNUM_FROM_CIDX_RW(cellidx, 1));
 
-       if (!(c->states & CAlias)) linkCount += 2;
+       linkCount += 2;
 
        afs_osi_Free(dotCell, dotLen);
        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);
@@ -343,7 +443,6 @@ afs_RefreshDynroot()
        ts = ts->next;
     }
 
-    newCellCount = maxcellidx + afs_dynSymlinkIndex;
     ReleaseReadLock(&afs_dynSymlinkLock);
 
     ObtainWriteLock(&afs_dynrootDirLock, 549);
@@ -351,51 +450,21 @@ afs_RefreshDynroot()
     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_dynrootVersion = 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, 0, 0, &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(dynrootDir, dynrootLen, status)
-    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);
     }
 
@@ -447,10 +516,11 @@ afs_DynrootNewVnode(avc, status)
     /*
      * 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));
@@ -487,7 +557,8 @@ afs_DynrootNewVnode(avc, status)
            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;
@@ -496,26 +567,26 @@ afs_DynrootNewVnode(avc, status)
        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;
@@ -525,7 +596,15 @@ afs_DynrootNewVnode(avc, status)
            }
 
            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"
             */
@@ -537,10 +616,10 @@ afs_DynrootNewVnode(avc, status)
            strcat(avc->linkData, ":root.cell");
 
            status->UnixModeBits = 0644;
+           afs_PutCell(c, READ_LOCK);
        }
 
        status->Length = linklen;
-       afs_PutCell(c, READ_LOCK);
        return 1;
     }
 
@@ -555,7 +634,7 @@ afs_SetDynrootEnable(enable)
     int enable;
 {
     afs_dynrootEnable = enable;
-    return 0;
+    return afs_dynrootCellInit();
 }
 
 /*
@@ -571,14 +650,11 @@ afs_GetDynrootEnable()
  * Remove a temporary symlink entry from /afs.
  */
 int
-afs_DynrootVOPRemove(avc, acred, aname)
-    struct vcache *avc;
-    struct AFS_UCRED *acred;
-    char *aname;
+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)
@@ -601,18 +677,14 @@ afs_DynrootVOPRemove(avc, acred, aname)
     }
     ReleaseWriteLock(&afs_dynSymlinkLock);
     if (found) {
-       afs_RefreshDynroot();
+       afs_DynrootInvalidate();
        return 0;
     }
 
-    /* Check if this is an actual cell? */
-    c = afs_GetCellByName2(aname, READ_LOCK, 0 /* no AFSDB */);
-    if (c) {
-       afs_PutCell(c, READ_LOCK);
+    if (afs_CellOrAliasExists(aname))
        return EROFS;
-    } else {
+    else 
        return ENOENT;
-    }
 }
 
 /*
@@ -626,17 +698,12 @@ afs_DynrootVOPSymlink(avc, acred, aname, atargetName)
     char *atargetName;
 {
     struct afs_dynSymlink *tps;
-    struct cell *c;
 
     if (acred->cr_uid)
        return EPERM;
 
-    /* Check if it's already a cell */
-    c = afs_GetCellByName2(aname, READ_LOCK, 0 /* no AFSDB */);
-    if (c) {
-       afs_PutCell(c, READ_LOCK);
-       return EEXIST;
-    }
+    if (afs_CellOrAliasExists(aname))
+        return EEXIST;
 
     /* Check if it's already a symlink */
     ObtainWriteLock(&afs_dynSymlinkLock, 91);
@@ -660,6 +727,6 @@ afs_DynrootVOPSymlink(avc, acred, aname, atargetName)
     afs_dynSymlinkBase = tps;
     ReleaseWriteLock(&afs_dynSymlinkLock);
 
-    afs_RefreshDynroot();
+    afs_DynrootInvalidate();
     return 0;
 }
index 7f830f2459acc569d8e75497141d539e3ff74735..5c64eb051fdf959349699471e810a53b7803cbae 100644 (file)
@@ -312,36 +312,50 @@ afs_ComputeCacheParms()
  *     WARNING: Data will be written to this file over time by AFS.
  */
 
-afs_InitVolumeInfo(afile)
-    register char *afile;
-
-{ /*afs_InitVolumeInfo*/
-
+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, (struct vnode **) 0, &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, (struct vnode **) 0, &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;
@@ -521,7 +535,6 @@ afs_ResourceInit(preallocs)
     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_xsrvAddr, "afs_xsrvAddr");
     RWLOCK_INIT(&afs_icl_lock, "afs_icl_lock");
@@ -533,6 +546,7 @@ afs_ResourceInit(preallocs)
     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) {
@@ -544,7 +558,6 @@ afs_ResourceInit(preallocs)
        afs_sysname = afs_sysnamelist[0];
        strcpy(afs_sysname, SYS_NAME);
        afs_sysnamecount = 1;
-       QInit(&CellLRU);        
 #if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
     {  extern afs_int32 afs_preallocs;
 
@@ -750,19 +763,6 @@ void shutdown_AFS()
     AFS_STATCNT(shutdown_AFS);
     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 
        */
@@ -859,19 +859,16 @@ void shutdown_AFS()
       afs_sysname = 0;
       afs_sysnamecount = 0;
       afs_marinerHost = 0;
-      QInit(&CellLRU);      
       afs_setTimeHost = (struct server *)0;
       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();
     }
     
 } /*shutdown_AFS*/
index 873f24ffbd18056a49194a38b6d7f2829b79d72a..301ac5f7aa4fae8647046d4d17792a5b3f362184 100644 (file)
@@ -22,8 +22,6 @@ RCSID("$Header$");
 
 
 
-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,
@@ -31,7 +29,6 @@ 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;
@@ -41,31 +38,19 @@ int afs_osi_vget(struct vcache **avcpp, struct fid *afidp,
 #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.
index 3bae148639f3883eaa119609caae1528643353ab..1b8912454da5eb7015717df0021d1d404b029a27 100644 (file)
@@ -1327,39 +1327,29 @@ static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
     return 0;
   }
   
-  static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
-    struct vcache *avc;
-  int afun;
-  struct vrequest *areq;
-  register char *ain;
-  char *aout;
-  afs_int32 ainSize;
-  afs_int32 *aoutSize; /* set this */ {
-    register struct cell *tcell=0, *cellOne=0;
-    register struct afs_q *cq, *tq;
+static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
+     struct vcache *avc;
+     int afun;
+     struct vrequest *areq;
+     register char *ain;
+     char *aout;
+     afs_int32 ainSize;
+     afs_int32 *aoutSize;      /* set this */ 
+{
+    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 = (struct cell *) 0;
-
-    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;
-  }
+}
   
   static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
     struct vcache *avc;
@@ -1454,20 +1444,15 @@ static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
          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;
@@ -1818,7 +1803,7 @@ static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
            }
        }
        else {
-           if (tu->uid == areq->uid && tu->cell == 1) break;
+           if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
        }
     }
     if (tu) {
@@ -2003,7 +1988,7 @@ static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
     else cellp = (struct cell *) 0;
     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 */
@@ -2342,7 +2327,7 @@ static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
     }
 
     linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
-    code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0, (char *) 0);
+    code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0);
     return code;
 }
 
@@ -2357,11 +2342,9 @@ static PNewAlias(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
     afs_int32 *aoutSize;       /* set this */
 {
     /* 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 */
@@ -2373,22 +2356,7 @@ static PNewAlias(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
     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;
 }
@@ -2404,7 +2372,6 @@ static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
     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 */
@@ -2412,7 +2379,7 @@ static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
 
     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));
@@ -2425,6 +2392,7 @@ static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
        strcpy(cp, tcell->cellName);
        cp += strlen(tcell->cellName)+1;
        *aoutSize = cp - aout;
+       afs_PutCell(tcell, READ_LOCK);
     }
     if (tcell) return 0;
     else return EDOM;
@@ -2439,9 +2407,8 @@ static PListAliases(avc, afun, areq, ain, aout, ainSize, aoutSize)
     afs_int32 *aoutSize;       /* set this */
 {
     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 */
@@ -2451,27 +2418,17 @@ static PListAliases(avc, afun, areq, ain, aout, ainSize, aoutSize)
     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;
 }
 
@@ -2956,10 +2913,22 @@ register struct AFS_UCRED *acred;
  * fine.  Should consider special-casing the local cell for large n.
  * Likewise for PSetSPrefs.
  */
-static void ReSortCells(s,l, vlonly)  
-  int s;     /* number of ids in array l[] -- NOT index of last id */
-  afs_int32 l[];  /* array of cell ids which have volumes that need to be sorted */
-  int vlonly; /* sort vl servers or file servers?*/
+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)  
 {
   extern struct volume *afs_volumes[NVOLS];   /* volume hash table */
 
@@ -2968,15 +2937,12 @@ static void ReSortCells(s,l, vlonly)
   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;
   }
 
@@ -3038,10 +3004,10 @@ static int afs_setsprefs(sp, num, vlonly)
         
         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);
index 2bbfc9eb8c3fbae8e7b132efa3481664e15d6521..52162ece773ae363bd1f638ead7beb87ba29f206 100644 (file)
@@ -18,9 +18,32 @@ extern int afs_Analyze(struct conn *aconn, afs_int32 acode, struct VenusFid *afi
                        struct cell *cellp);
 
 /* afs_cell.c */
-extern struct cell *afs_GetRealCellByIndex(register afs_int32 cellindex,
-                                          afs_int32 locktype,
-                                          afs_int32 refresh);
+extern afs_rwlock_t afs_xcell;
+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_conn.c */
 extern struct conn *afs_ConnBySA(struct srvAddr *sap, unsigned short aport,
@@ -28,6 +51,7 @@ extern struct conn *afs_ConnBySA(struct srvAddr *sap, unsigned short aport,
                          int force_if_down, afs_int32 create, afs_int32 locktype);
 
 /* afs_dcache.c */
+extern int cacheDiskType;
 extern void afs_dcacheInit(int afiles, int ablocks, int aDentries, int achunk,
                           int aflags);
 
@@ -84,6 +108,7 @@ extern void afs_GCPAGs_perproc_func(AFS_PROC *pproc);
 
 /* afs_util.c */
 extern char *afs_cv2string(char *ttp, afs_uint32 aval);
+extern int afs_strcasecmp(char *s1, char *s2);
 extern char *afs_strchr(char *s, int c);
 extern void print_internet_address(char *preamble, struct srvAddr *sa,
                            char *postamble, int flag);
index b8019a46a3dd44a750a078cdb3a2ec9b6f2fe821..785891dac33765f7dbdd4802fb16020167aaaa81 100644 (file)
@@ -90,6 +90,26 @@ int afs_totalSrvAddrs = 0;
 
 
 
+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
@@ -165,16 +185,7 @@ void afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
     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) {
        /*
@@ -295,7 +306,7 @@ static void CheckVLServer(sa, areq)
        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);
@@ -429,17 +440,7 @@ void afs_CountServers()
                 * 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))
@@ -568,8 +569,8 @@ void afs_CheckServers(adown, acellp)
            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;
@@ -602,12 +603,9 @@ void afs_CheckServers(adown, acellp)
             */
            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 */
@@ -1605,16 +1603,8 @@ struct server *afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers,
        /* 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;
@@ -1642,21 +1632,12 @@ void afs_ActivateServer(sap)
       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++;
       }
    }
 }
index d595c0c203cd1603414e95a793a8ab6b134e8f5a..39dfcd0d030272f148e1df2a4e1c16f646cca60e 100644 (file)
@@ -637,6 +637,8 @@ struct afs_CMCallStats {
     afs_int32 C_SRXAFSCB_GetLocalCell; /* afs_callback.c*/
     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 {
index 4dce21619c56e2b81147ca7c6596719408cd52d0..f91daeb61d8eb72831c0f46b4e82fdfd17462491 100644 (file)
@@ -374,7 +374,7 @@ afs_int32 afs_FlushVCBs (afs_int32 lockit)
                    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);
@@ -632,9 +632,7 @@ restart:
  *     entries locked.
  */
 
-afs_RemoveVCB(afid)
-    register struct VenusFid *afid;
-
+afs_RemoveVCB(struct VenusFid *afid)
 { /*afs_RemoveVCB*/
 
     register int i, j;
@@ -648,7 +646,7 @@ afs_RemoveVCB(afid)
     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
@@ -2530,7 +2528,7 @@ struct vcache *afs_FindVCache(struct VenusFid *afid, afs_int32 lockit,
     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++;
@@ -2672,7 +2670,7 @@ afs_int32 afs_NFSFindVCache(avcp, afid, lockit)
 
     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++;
index d75eb169602ca03799e911db1fd58daffc8b7114..89d1e35cd64f4b2b026792bfbb88eb07fa5ed742 100644 (file)
@@ -112,7 +112,7 @@ struct volume *afs_UFSGetVolSlot()
 
 {
     register struct volume *tv, **lv;
-    register char *tfile;
+    struct osi_file *tfile;
     register afs_int32 i, code;
     afs_int32 bestTime;
     struct volume *bestVp, **bestLp;
@@ -461,7 +461,7 @@ static struct volume *afs_SetupVolume(volid, aname, ve, tcell, agood, type, areq
     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;
        }
     }
@@ -470,14 +470,14 @@ static struct volume *afs_SetupVolume(volid, aname, ve, tcell, agood, type, areq
 
        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))
@@ -506,12 +506,12 @@ static struct volume *afs_SetupVolume(volid, aname, ve, tcell, agood, type, areq
     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);
@@ -573,7 +573,7 @@ static struct volume *afs_NewDynrootVolume(struct VenusFid *fid) {
     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;
 }
@@ -614,7 +614,7 @@ static struct volume *afs_NewVolumeByName(char *aname, afs_int32 acell, int agoo
     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;
@@ -947,7 +947,7 @@ void InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve,
                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) {
 #ifdef RX_ENABLE_LOCKS
                        AFS_GUNLOCK();
index d2921d532903f6707eae573e56f28ce8e82dfa70..7d9aa5c9640c4d2c7940b4c3c0285497c2fde47e 100644 (file)
@@ -170,6 +170,7 @@ void set_staticaddrs(void);
 #define        AFSLOGFILE      "AFSLog"
 #define        DCACHEFILE      "CacheItems"
 #define        VOLINFOFILE     "VolumeItems"
+#define CELLINFOFILE   "CellItems"
 
 #define MAXIPADDRS 1024
 
@@ -211,6 +212,7 @@ char cacheBaseDir[1024];            /*Where the workstation AFS cache lives*/
 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*/
@@ -224,7 +226,6 @@ char cacheMountDir[1024];           /*Mount directory for AFS*/
 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*/
@@ -270,10 +271,11 @@ int *dir_for_V = NULL;                    /* Array: dir of each cache file.
                                         */
 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();
 
@@ -626,6 +628,16 @@ int CreateCacheFile(fname, statp)
     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
   *
@@ -802,6 +814,12 @@ static int doSweepAFSCache(vFilesFound,directory,dirNum,maxDir)
             */
            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
@@ -842,25 +860,12 @@ static int doSweepAFSCache(vFilesFound,directory,dirNum,maxDir)
 
     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 */
 
@@ -1035,19 +1040,14 @@ register struct afsconf_cell *aci;
 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++)
@@ -1057,11 +1057,13 @@ struct afsconf_dir *adir; {
                                            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;
 }
 
@@ -1472,8 +1474,9 @@ mainproc(as, arock)
     /*
      * 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);
 
@@ -1572,6 +1575,83 @@ mainproc(as, arock)
     }
 #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);
@@ -1646,19 +1726,13 @@ mainproc(as, arock)
     /*
      * Tell the kernel about each cell in the configuration.
      */
-    lookingForHomeCell = 1;
-
     afsconf_CellApply(cdir, ConfigCell, (char *) 0);
     afsconf_CellAliasApply(cdir, ConfigCellAlias, (char *) 0);
 
     /*
-     * 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.
@@ -1670,67 +1744,6 @@ mainproc(as, arock)
        call_syscall(AFSOP_ROOTVOLUME, rootVolume);
     }
 
-    /*
-     * 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.
index ab8d095eed5b1c6d977a3744531774d8ab9ac6c9..688fa68d64d51a3aab1814b564c40b5bc95aab1d 100644 (file)
@@ -42,6 +42,9 @@
 #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
index a8ce0c153236e20f6dc9f82e963b23642bf79138..c1bae1c50a79e6d1e5b0471555a7d41ad3777c6b 100644 (file)
@@ -96,3 +96,9 @@ proc GetCacheConfig(
   OUT cacheConfig *config
 ) = 218;
 
+proc GetCellByNum(
+  IN  afs_int32 cellNumber,
+  OUT string cellName<AFSNAMEMAX>,
+  OUT serverList *cellHosts
+) = 65537;
+
index 6157643a5124f802cb189009d7551a535dda73e0..630fccd9c94c2afbc08ee1fc20747a53304b700a 100644 (file)
@@ -646,6 +646,15 @@ int SRXAFSCB_GetCellServDB(
     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
  *
index 182f5a418f68a358066da6da0ed9e00c932d564a..a37a9f59bcbccef0d2e733c9b4d74de77fa8e857 100644 (file)
@@ -89,12 +89,55 @@ register struct rx_connection *aconn; {
     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, &centry);
@@ -115,8 +158,16 @@ register struct rx_connection *aconn; {
        if (!aint32 && !IsLocked(&centry.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(&centry.lock)) {
            printf("    locks: ");
            PrintLock(&centry.lock);
index 91e7a4d8d0693a0b664199186b0ebe1323abc579..debfd8c21c33dbe8902ac0e316b3494dd53c9cab 100644 (file)
@@ -1053,6 +1053,8 @@ kdump()
 
     if (Dcells || Dall) {
        print_cells(1); /* Handle the afs_cells structures */
+       print_cellaliases(1);
+       print_cellnames(1);
     }
 
     if (Dusers || Dall) {
@@ -1170,6 +1172,7 @@ kdump()
 #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;
@@ -1193,6 +1196,64 @@ 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;
 }
 
@@ -1761,6 +1822,18 @@ int pnt;
     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;
@@ -2268,9 +2341,10 @@ void print_cell(kmem, clep, ptr, pnt)
     cellName[40] = 0;
     Sum_cellnames += strlen(cellName)+1;
     if (pnt) {
-       printf("%lx: cell=%s, cellname=%s, states=%x, cindex=%d fsport=%d vlport=%d\n", ptr,
-              PrintIPAddr(clep->cell), cellName, clep->states, clep->cellIndex,
-              clep->fsport, clep->vlport);
+       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);
index e9ec600b83caeb7a9a71d9e0edbb73ab7d3c714c..72186326d1dc819d8e9f4160715082d8c029866e 100644 (file)
@@ -55,7 +55,7 @@ RCSID("$Header$");
 #include <unistd.h>
 #endif /* AFS_NT40_ENV */
 #include <sys/stat.h>
-
+#include <stdarg.h>
 
 struct VnodeClassInfo VnodeClassInfo[nVNODECLASSES];
 
index e5e2356ce45de8e7b196bd11df069775be053de2..ec137f5ce4aad7769611cf93430248ca6c580e9a 100644 (file)
@@ -652,6 +652,16 @@ int SRXAFSCB_GetCellServDB(
 }
 
 
+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
  *