mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 06:50:12 +00:00
unix-dynroot-support-20011009
The result is that if afsd is started with "-dynroot", /afs will be a locally-generated directory, with mountpoints for every cell in CellServDB (and /afs/.cellname as the rw mountpoint). If AFSDB support is also enabled, attempting to access /afs/foo will cause the cache manager to do an AFSDB lookup on foo, similar to an automounter. Cell aliases become symlinks to the real cell names under /afs.
This commit is contained in:
parent
56fa8cca37
commit
077c0a4d76
9
NEWS
9
NEWS
@ -1,11 +1,18 @@
|
||||
Openafs News -- history of user Visible changes. September 17, 2001
|
||||
OpenAFS News -- history of user-visible changes. October 9, 2001
|
||||
|
||||
* Changes incorporated in OpenAFS 1.2.2
|
||||
|
||||
** If afsd is started with the -dynroot flag, /afs will be locally
|
||||
generated from the CellServDB. AFSDB cells will be mounted
|
||||
automatically upon access.
|
||||
|
||||
** The namei fileserver allows vice "partitions" to be directories instead
|
||||
of partitions and will attach and display accordingly. Creating the file
|
||||
"AlwaysAttach" in the /vicepX directory is used as the trigger to attach it.
|
||||
|
||||
** TSM support for butc no longer requires editing a Makefile, simply
|
||||
specify the --enable-tivoli-tsm configure option.
|
||||
|
||||
** Linux builds no longer require source changes every time the kernel
|
||||
inode structure changes; the OpenAFS sources will now configure
|
||||
itself to the actual inode structure as defined in the kernel
|
||||
|
1
README
1
README
@ -39,6 +39,7 @@ A. Creating the proper directory structure.
|
||||
sun4x_56
|
||||
sun4x_57
|
||||
sun4x_58
|
||||
sun4x_59
|
||||
ppc_darwin_13
|
||||
ppc_linux22
|
||||
ppc_linux24
|
||||
|
@ -912,6 +912,7 @@ afs_lookup(adp, aname, avcp, acred)
|
||||
afs_hyper_t versionNo;
|
||||
int no_read_access = 0;
|
||||
struct sysname_info sysState; /* used only for @sys checking */
|
||||
int dynrootRetry = 1;
|
||||
|
||||
AFS_STATCNT(afs_lookup);
|
||||
#ifdef AFS_OSF_ENV
|
||||
@ -1112,9 +1113,27 @@ afs_lookup(adp, aname, avcp, acred)
|
||||
}
|
||||
tname = sysState.name;
|
||||
|
||||
ReleaseReadLock(&adp->lock);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
ReleaseReadLock(&adp->lock);
|
||||
}
|
||||
|
||||
/* new fid has same cell and volume */
|
||||
tfid.Cell = adp->fid.Cell;
|
||||
tfid.Fid.Volume = adp->fid.Fid.Volume;
|
||||
@ -1132,7 +1151,7 @@ afs_lookup(adp, aname, avcp, acred)
|
||||
/* prefetch some entries, if the dir is currently open. The variable
|
||||
* dirCookie tells us where to start prefetching from.
|
||||
*/
|
||||
if (AFSDOBULK && adp->opens > 0 && !(adp->states & CForeign)) {
|
||||
if (AFSDOBULK && adp->opens > 0 && !(adp->states & CForeign) && !afs_IsDynroot(adp)) {
|
||||
afs_int32 retry;
|
||||
/* if the entry is not in the cache, or is in the cache,
|
||||
* but hasn't been statd, then do a bulk stat operation.
|
||||
|
@ -960,6 +960,7 @@ extern struct brequest afs_brs[NBRS]; /* request structures */
|
||||
|
||||
extern struct cell *afs_GetCell();
|
||||
extern struct cell *afs_GetCellByName();
|
||||
extern struct cell *afs_GetCellByIndex();
|
||||
extern struct unixuser *afs_GetUser();
|
||||
extern struct volume *afs_GetVolume();
|
||||
extern struct volume *afs_GetVolumeByName();
|
||||
@ -992,6 +993,17 @@ extern void afs_shutdown();
|
||||
/* afs_osifile.c */
|
||||
extern void shutdown_osifile();
|
||||
|
||||
/* afs_dynroot.c */
|
||||
extern int afs_IsDynrootFid();
|
||||
extern void afs_GetDynrootFid();
|
||||
extern int afs_IsDynroot();
|
||||
extern void afs_RefreshDynroot();
|
||||
extern void afs_GetDynroot();
|
||||
extern void afs_PutDynroot();
|
||||
extern int afs_DynrootNewVnode();
|
||||
extern int afs_SetDynrootEnable();
|
||||
extern int afs_GetDynrootEnable();
|
||||
|
||||
|
||||
/* Performance hack - we could replace VerifyVCache2 with the appropriate
|
||||
* GetVCache incantation, and could eliminate even this code from afs_UFSRead
|
||||
@ -1050,6 +1062,7 @@ extern int afs_CacheTooFull;
|
||||
* afs_GetDownD wakes those processes once the cache is 95% full
|
||||
* (CM_CACHESIZEDRAINEDPCT).
|
||||
*/
|
||||
extern void afs_MaybeWakeupTruncateDaemon();
|
||||
extern void afs_CacheTruncateDaemon();
|
||||
extern int afs_WaitForCacheDrain;
|
||||
#define CM_MAXDISCARDEDCHUNKS 16 /* # of chunks */
|
||||
@ -1065,19 +1078,6 @@ extern int afs_WaitForCacheDrain;
|
||||
afs_freeDCCount - afs_discardDCCount < \
|
||||
((100-CM_DCACHECOUNTFREEPCT)*afs_cacheFiles)/100)
|
||||
|
||||
#define afs_MaybeWakeupTruncateDaemon() \
|
||||
do { \
|
||||
if (!afs_CacheTooFull && afs_CacheIsTooFull()) { \
|
||||
afs_CacheTooFull = 1; \
|
||||
if (!afs_TruncateDaemonRunning) { \
|
||||
afs_osi_Wakeup((char *)afs_CacheTruncateDaemon); \
|
||||
} \
|
||||
} else if (!afs_TruncateDaemonRunning && \
|
||||
afs_blocksDiscarded > CM_MAXDISCARDEDCHUNKS) { \
|
||||
afs_osi_Wakeup((char *)afs_CacheTruncateDaemon); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Handy max length of a numeric string. */
|
||||
#define CVBS 12 /* max afs_int32 is 2^32 ~ 4*10^9, +1 for NULL, +luck */
|
||||
|
||||
|
@ -625,6 +625,9 @@ long parm, parm2, parm3, parm4, parm5, parm6;
|
||||
afs_osi_Free(cellname, cellLen);
|
||||
}
|
||||
#endif
|
||||
else if (parm == AFSOP_SET_DYNROOT) {
|
||||
code = afs_SetDynrootEnable(parm2);
|
||||
}
|
||||
else
|
||||
code = EINVAL;
|
||||
|
||||
|
@ -268,6 +268,7 @@ void afs_Daemon() {
|
||||
afs_CheckRootVolume () {
|
||||
char rootVolName[32];
|
||||
register struct volume *tvp;
|
||||
int usingDynroot = afs_GetDynrootEnable();
|
||||
|
||||
AFS_STATCNT(afs_CheckRootVolume);
|
||||
if (*afs_rootVolumeName == 0) {
|
||||
@ -276,7 +277,12 @@ afs_CheckRootVolume () {
|
||||
else {
|
||||
strcpy(rootVolName, afs_rootVolumeName);
|
||||
}
|
||||
tvp = afs_GetVolumeByName(rootVolName, LOCALCELL, 1, (struct vrequest *) 0, READ_LOCK);
|
||||
if (usingDynroot) {
|
||||
afs_GetDynrootFid(&afs_rootFid);
|
||||
tvp = afs_GetVolume(&afs_rootFid, (struct vrequest *) 0, READ_LOCK);
|
||||
} else {
|
||||
tvp = afs_GetVolumeByName(rootVolName, LOCALCELL, 1, (struct vrequest *) 0, READ_LOCK);
|
||||
}
|
||||
if (!tvp) {
|
||||
char buf[128];
|
||||
int len = strlen(rootVolName);
|
||||
@ -288,23 +294,25 @@ afs_CheckRootVolume () {
|
||||
}
|
||||
}
|
||||
if (tvp) {
|
||||
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;
|
||||
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_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);
|
||||
|
@ -218,6 +218,17 @@ struct CTD_stats {
|
||||
int CTD_nSleeps;
|
||||
} CTD_stats;
|
||||
|
||||
void afs_MaybeWakeupTruncateDaemon() {
|
||||
if (!afs_CacheTooFull && afs_CacheIsTooFull()) {
|
||||
afs_CacheTooFull = 1;
|
||||
if (!afs_TruncateDaemonRunning)
|
||||
afs_osi_Wakeup((char *)afs_CacheTruncateDaemon);
|
||||
} else if (!afs_TruncateDaemonRunning &&
|
||||
afs_blocksDiscarded > CM_MAXDISCARDEDCHUNKS) {
|
||||
afs_osi_Wakeup((char *)afs_CacheTruncateDaemon);
|
||||
}
|
||||
}
|
||||
|
||||
u_int afs_min_cache = 0;
|
||||
void afs_CacheTruncateDaemon() {
|
||||
osi_timeval_t CTD_tmpTime;
|
||||
@ -1436,18 +1447,19 @@ struct tlocal1 {
|
||||
|
||||
/* these fields are protected by the lock on the vcache and luck
|
||||
* on the dcache */
|
||||
#define updateV2DC(l,v,d,src) { \
|
||||
if (!l || 0 == NBObtainWriteLock(&((v)->lock),src)) { \
|
||||
if (hsame((v)->m.DataVersion, (d)->f.versionNo) && (v)->callback) { \
|
||||
(v)->quick.dc = (d); \
|
||||
(v)->quick.stamp = (d)->stamp = MakeStamp(); \
|
||||
(v)->quick.minLoc = AFS_CHUNKTOBASE((d)->f.chunk); \
|
||||
/* Don't think I need these next two lines forever */ \
|
||||
(v)->quick.len = (d)->f.chunkBytes; \
|
||||
(v)->h1.dchint = (d); \
|
||||
} \
|
||||
if(l) ReleaseWriteLock(&((v)->lock)); \
|
||||
} }
|
||||
void updateV2DC(int l, struct vcache *v, struct dcache *d, int src) {
|
||||
if (!l || 0 == NBObtainWriteLock(&(v->lock),src)) {
|
||||
if (hsame(v->m.DataVersion, d->f.versionNo) && v->callback) {
|
||||
v->quick.dc = d;
|
||||
v->quick.stamp = d->stamp = MakeStamp();
|
||||
v->quick.minLoc = AFS_CHUNKTOBASE(d->f.chunk);
|
||||
/* Don't think I need these next two lines forever */
|
||||
v->quick.len = d->f.chunkBytes;
|
||||
v->h1.dchint = d;
|
||||
}
|
||||
if(l) ReleaseWriteLock(&((v)->lock));
|
||||
}
|
||||
}
|
||||
|
||||
struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags)
|
||||
register struct vcache *avc; /*Held*/
|
||||
@ -1773,7 +1785,7 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags)
|
||||
|
||||
/* Watch for standard race condition */
|
||||
if (hsame(avc->m.DataVersion, tdc->f.versionNo)) {
|
||||
updateV2DC(0,avc,tdc,569); /* set hint */
|
||||
updateV2DC(0,avc,tdc,569); /* set hint */
|
||||
if (setLocks) ReleaseWriteLock(&avc->lock);
|
||||
afs_stats_cmperf.dcacheHits++;
|
||||
goto done;
|
||||
@ -1868,6 +1880,35 @@ struct dcache *afs_GetDCache(avc, abyte, areq, aoffset, alen, aflags)
|
||||
afs_stats_cmperf.dcacheMisses++;
|
||||
afs_Trace3(afs_iclSetp, CM_TRACE_FETCHPROC, ICL_TYPE_POINTER, avc,
|
||||
ICL_TYPE_INT32, Position, ICL_TYPE_INT32, size);
|
||||
|
||||
/*
|
||||
* Dynamic root support: fetch data from local memory.
|
||||
*/
|
||||
if (afs_IsDynroot(avc)) {
|
||||
char *dynrootDir;
|
||||
int dynrootLen;
|
||||
|
||||
afs_GetDynroot(&dynrootDir, &dynrootLen, &tsmall->OutStatus);
|
||||
|
||||
dynrootDir += Position;
|
||||
dynrootLen -= Position;
|
||||
if (size > dynrootLen)
|
||||
size = dynrootLen;
|
||||
if (size < 0) size = 0;
|
||||
code = afs_osi_Write(file, -1, dynrootDir, size);
|
||||
afs_PutDynroot();
|
||||
|
||||
if (code == size)
|
||||
code = 0;
|
||||
else
|
||||
code = -1;
|
||||
|
||||
tdc->validPos = Position + size;
|
||||
afs_CFileTruncate(file, size); /* prune it */
|
||||
} else
|
||||
/*
|
||||
* Not a dynamic vnode: do the real fetch.
|
||||
*/
|
||||
do {
|
||||
tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
|
||||
if (tc) {
|
||||
|
461
src/afs/afs_dynroot.c
Normal file
461
src/afs/afs_dynroot.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
* Copyright 2000, International Business Machines Corporation and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dynamic /afs volume support.
|
||||
*
|
||||
* Implements:
|
||||
* afs_IsDynrootFid
|
||||
* afs_GetDynrootFid
|
||||
* afs_IsDynroot
|
||||
* afs_RefreshDynroot
|
||||
* afs_GetDynroot
|
||||
* afs_PutDynroot
|
||||
* afs_DynrootNewVnode
|
||||
* afs_SetDynrootEnable
|
||||
* afs_GetDynrootEnable
|
||||
*
|
||||
*/
|
||||
|
||||
#include <afsconfig.h>
|
||||
#include "../afs/param.h"
|
||||
|
||||
#include "../afs/stds.h"
|
||||
#include "../afs/sysincludes.h" /* Standard vendor system headers */
|
||||
#include "../afs/afsincludes.h"
|
||||
#include "../afs/afs_osi.h"
|
||||
#include "../afsint/afsint.h"
|
||||
#include "../afs/lock.h"
|
||||
|
||||
#include "../afs/prs_fs.h"
|
||||
#include "../afs/dir.h"
|
||||
|
||||
#define AFS_DYNROOT_CELL 1
|
||||
#define AFS_DYNROOT_VOLUME 1
|
||||
#define AFS_DYNROOT_VNODE 1
|
||||
#define AFS_DYNROOT_UNIQUE 1
|
||||
|
||||
#define VNUM2CIDX(vnum) ((vnum) >> 2)
|
||||
#define VNUM2RW(vnum) (((vnum) >> 1) & 1)
|
||||
#define CIDXRW2VNUM(cidx, rw) (((cidx) << 2) | ((rw) << 1))
|
||||
|
||||
static int afs_dynrootEnable = 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_dynrootVersion = 1;
|
||||
static int afs_dynrootVersionHigh = 1;
|
||||
/* End of variables protected by afs_dynrootDirLock */
|
||||
|
||||
extern afs_int32 afs_cellindex;
|
||||
extern afs_rwlock_t afs_xvcache;
|
||||
|
||||
/*
|
||||
* Returns non-zero iff fid corresponds to the top of the dynroot volume.
|
||||
*/
|
||||
int
|
||||
afs_IsDynrootFid(struct VenusFid *fid)
|
||||
{
|
||||
return
|
||||
(afs_dynrootEnable &&
|
||||
fid->Cell == AFS_DYNROOT_CELL &&
|
||||
fid->Fid.Volume == AFS_DYNROOT_VOLUME &&
|
||||
fid->Fid.Vnode == AFS_DYNROOT_VNODE &&
|
||||
fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the magic dynroot volume Fid.
|
||||
*/
|
||||
void
|
||||
afs_GetDynrootFid(struct VenusFid *fid)
|
||||
{
|
||||
fid->Cell = AFS_DYNROOT_CELL;
|
||||
fid->Fid.Volume = AFS_DYNROOT_VOLUME;
|
||||
fid->Fid.Vnode = AFS_DYNROOT_VNODE;
|
||||
fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero iff avc is a pointer to the dynroot /afs vnode.
|
||||
*/
|
||||
int
|
||||
afs_IsDynroot(avc)
|
||||
struct vcache *avc;
|
||||
{
|
||||
return afs_IsDynrootFid(&avc->fid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add directory entry by given name to a directory. Assumes the
|
||||
* caller has allocated the directory to be large enough to hold
|
||||
* the necessary entry.
|
||||
*/
|
||||
static void
|
||||
afs_dynroot_addDirEnt(dirHeader, curPageP, curChunkP, name, vnode)
|
||||
struct DirHeader *dirHeader;
|
||||
int *curPageP;
|
||||
int *curChunkP;
|
||||
char *name;
|
||||
int vnode;
|
||||
{
|
||||
char *dirBase = (char *) dirHeader;
|
||||
struct PageHeader *pageHeader;
|
||||
struct DirEntry *dirEntry;
|
||||
int sizeOfEntry, i, t1, t2;
|
||||
int curPage = *curPageP;
|
||||
int curChunk = *curChunkP;
|
||||
int didNewPage = 0;
|
||||
|
||||
/*
|
||||
* Check if we need to flip pages.. If so, init the new page.
|
||||
*/
|
||||
sizeOfEntry = afs_dir_NameBlobs(name);
|
||||
if (curChunk + sizeOfEntry > EPP) {
|
||||
curPage++;
|
||||
curChunk = 1;
|
||||
didNewPage = 1;
|
||||
}
|
||||
|
||||
pageHeader = (struct PageHeader *) (dirBase + curPage * AFS_PAGESIZE);
|
||||
if (didNewPage) {
|
||||
pageHeader->pgcount = 0;
|
||||
pageHeader->tag = htons(1234);
|
||||
pageHeader->freecount = 0;
|
||||
pageHeader->freebitmap[0] = 0x01;
|
||||
for (i = 1; i < EPP/8; i++)
|
||||
pageHeader->freebitmap[i] = 0;
|
||||
|
||||
dirHeader->alloMap[curPage] = EPP - 1;
|
||||
}
|
||||
|
||||
dirEntry = (struct DirEntry *) (pageHeader + curChunk);
|
||||
dirEntry->flag = 1;
|
||||
dirEntry->length = 0;
|
||||
dirEntry->next = 0;
|
||||
dirEntry->fid.vnode = htonl(vnode);
|
||||
dirEntry->fid.vunique = htonl(1);
|
||||
strcpy(dirEntry->name, name);
|
||||
|
||||
for (i = curChunk; i < curChunk + sizeOfEntry; i++) {
|
||||
t1 = i / 8;
|
||||
t2 = i % 8;
|
||||
pageHeader->freebitmap[t1] |= (1 << t2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the new entry to the correct hash chain.
|
||||
*/
|
||||
i = DirHash(name);
|
||||
dirEntry->next = dirHeader->hashTable[i];
|
||||
dirHeader->hashTable[i] = htons(curPage * EPP + curChunk);
|
||||
|
||||
curChunk += sizeOfEntry;
|
||||
dirHeader->alloMap[curPage] -= sizeOfEntry;
|
||||
|
||||
*curPageP = curPage;
|
||||
*curChunkP = curChunk;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
int cellidx, maxcellidx, i;
|
||||
struct cell *c;
|
||||
int curChunk, curPage;
|
||||
int dirSize;
|
||||
char *newDir, *dotCell;
|
||||
struct DirHeader *dirHeader;
|
||||
struct PageHeader *pageHeader;
|
||||
struct DirEntry *dirEntry;
|
||||
int doFlush = 0;
|
||||
int linkCount = 0;
|
||||
|
||||
/*
|
||||
* Save afs_cellindex here, in case it changes between the
|
||||
* two loops.
|
||||
*/
|
||||
maxcellidx = afs_cellindex;
|
||||
|
||||
/*
|
||||
* Compute the amount of space we need for the fake dir
|
||||
*/
|
||||
curChunk = 13;
|
||||
curPage = 0;
|
||||
|
||||
for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
|
||||
int sizeOfCurEntry;
|
||||
|
||||
c = afs_GetCellByIndex(cellidx, READ_LOCK);
|
||||
if (!c) continue;
|
||||
|
||||
sizeOfCurEntry = afs_dir_NameBlobs(c->cellName);
|
||||
if (curChunk + sizeOfCurEntry > EPP) {
|
||||
curPage++;
|
||||
curChunk = 1;
|
||||
}
|
||||
curChunk += sizeOfCurEntry;
|
||||
|
||||
dotCell = afs_osi_Alloc(strlen(c->cellName) + 2);
|
||||
strcpy(dotCell, ".");
|
||||
strcat(dotCell, c->cellName);
|
||||
sizeOfCurEntry = afs_dir_NameBlobs(dotCell);
|
||||
if (curChunk + sizeOfCurEntry > EPP) {
|
||||
curPage++;
|
||||
curChunk = 1;
|
||||
}
|
||||
curChunk += sizeOfCurEntry;
|
||||
|
||||
afs_PutCell(c, READ_LOCK);
|
||||
}
|
||||
|
||||
dirSize = (curPage + 1) * AFS_PAGESIZE;
|
||||
newDir = afs_osi_Alloc(dirSize);
|
||||
|
||||
/*
|
||||
* Now actually construct the directory.
|
||||
*/
|
||||
curChunk = 13;
|
||||
curPage = 0;
|
||||
dirHeader = (struct DirHeader *) newDir;
|
||||
|
||||
dirHeader->header.pgcount = 0;
|
||||
dirHeader->header.tag = htons(1234);
|
||||
dirHeader->header.freecount = 0;
|
||||
|
||||
dirHeader->header.freebitmap[0] = 0xff;
|
||||
dirHeader->header.freebitmap[1] = 0x1f;
|
||||
for (i = 2; i < EPP/8; i++)
|
||||
dirHeader->header.freebitmap[i] = 0;
|
||||
dirHeader->alloMap[0] = EPP - DHE - 1;
|
||||
for (i = 1; i < MAXPAGES; i++)
|
||||
dirHeader->alloMap[i] = EPP;
|
||||
for (i = 0; i < NHASHENT; i++)
|
||||
dirHeader->hashTable[i] = 0;
|
||||
|
||||
/* Install "." and ".." */
|
||||
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
|
||||
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
|
||||
linkCount += 2;
|
||||
|
||||
for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
|
||||
c = afs_GetCellByIndex(cellidx, READ_LOCK);
|
||||
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
|
||||
c->cellName, CIDXRW2VNUM(cellidx, 0));
|
||||
|
||||
dotCell = afs_osi_Alloc(strlen(c->cellName) + 2);
|
||||
strcpy(dotCell, ".");
|
||||
strcat(dotCell, c->cellName);
|
||||
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
|
||||
dotCell, CIDXRW2VNUM(cellidx, 1));
|
||||
|
||||
linkCount += 2;
|
||||
|
||||
afs_PutCell(c, READ_LOCK);
|
||||
}
|
||||
|
||||
ObtainWriteLock(&afs_dynrootDirLock, 549);
|
||||
if (afs_dynrootDir) afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
|
||||
afs_dynrootDir = newDir;
|
||||
afs_dynrootDirLen = dirSize;
|
||||
afs_dynrootDirLinkcnt = linkCount;
|
||||
if (afs_dynrootCellCount != maxcellidx) {
|
||||
/*
|
||||
* New cells added -- bump data version, invalidate vcache.
|
||||
*/
|
||||
afs_dynrootCellCount = maxcellidx;
|
||||
afs_dynrootVersion++;
|
||||
afs_dynrootVersionHigh = osi_Time();
|
||||
doFlush = 1;
|
||||
}
|
||||
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;
|
||||
{
|
||||
ObtainReadLock(&afs_dynrootDirLock);
|
||||
if (!afs_dynrootDir) {
|
||||
ReleaseReadLock(&afs_dynrootDirLock);
|
||||
afs_RefreshDynroot();
|
||||
ObtainReadLock(&afs_dynrootDirLock);
|
||||
}
|
||||
|
||||
if (dynrootDir) *dynrootDir = afs_dynrootDir;
|
||||
if (dynrootLen) *dynrootLen = afs_dynrootDirLen;
|
||||
|
||||
if (status) {
|
||||
memset(status, 0, sizeof(struct AFSFetchStatus));
|
||||
status->FileType = Directory;
|
||||
status->LinkCount = afs_dynrootDirLinkcnt;
|
||||
status->Length = afs_dynrootDirLen;
|
||||
status->DataVersion = afs_dynrootVersion;
|
||||
status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
|
||||
status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
|
||||
status->UnixModeBits = 0755;
|
||||
status->ParentVnode = 1;
|
||||
status->ParentUnique = 1;
|
||||
status->dataVersionHigh = afs_dynrootVersionHigh;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Puts back the dynroot read lock.
|
||||
*/
|
||||
void
|
||||
afs_PutDynroot()
|
||||
{
|
||||
ReleaseReadLock(&afs_dynrootDirLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform dynroot that a new vnode is being created. Return value
|
||||
* is non-zero if this vnode is handled by dynroot, in which case
|
||||
* FetchStatus will be filled in.
|
||||
*/
|
||||
int
|
||||
afs_DynrootNewVnode(avc, status)
|
||||
struct vcache *avc;
|
||||
struct AFSFetchStatus *status;
|
||||
{
|
||||
if (!afs_dynrootEnable) return 0;
|
||||
|
||||
if (afs_IsDynroot(avc)) {
|
||||
afs_GetDynroot(0, 0, status);
|
||||
afs_PutDynroot();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if this is an entry under /afs, e.g. /afs/cellname.
|
||||
*/
|
||||
if (avc->fid.Cell == AFS_DYNROOT_CELL &&
|
||||
avc->fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
|
||||
|
||||
struct cell *c;
|
||||
int namelen, linklen, cellidx, rw;
|
||||
|
||||
cellidx = VNUM2CIDX(avc->fid.Fid.Vnode);
|
||||
rw = VNUM2RW(avc->fid.Fid.Vnode);
|
||||
|
||||
c = afs_GetCellByIndex(cellidx, READ_LOCK);
|
||||
if (!c) {
|
||||
afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
|
||||
cellidx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(status, 0, sizeof(struct AFSFetchStatus));
|
||||
|
||||
if (c->states & CAlias) {
|
||||
/*
|
||||
* linkData needs to contain the name of the cell
|
||||
* we're aliasing for.
|
||||
*/
|
||||
struct cell *tca = c->alias;
|
||||
|
||||
if (!tca) {
|
||||
afs_warn("dynroot: alias %s missing cell alias pointer\n",
|
||||
c->cellName);
|
||||
linklen = 7;
|
||||
avc->linkData = afs_osi_Alloc(linklen + 1);
|
||||
strcpy(avc->linkData, "unknown");
|
||||
} else {
|
||||
int namelen = strlen(tca->cellName);
|
||||
linklen = rw + namelen;
|
||||
avc->linkData = afs_osi_Alloc(linklen + 1);
|
||||
strcpy(avc->linkData, rw ? "." : "");
|
||||
strcat(avc->linkData, tca->cellName);
|
||||
}
|
||||
|
||||
status->UnixModeBits = 0755;
|
||||
} else {
|
||||
/*
|
||||
* linkData needs to contain "#cell:root.cell" or "%cell:root.cell"
|
||||
*/
|
||||
namelen = strlen(c->cellName);
|
||||
linklen = 1 + namelen + 10;
|
||||
avc->linkData = afs_osi_Alloc(linklen + 1);
|
||||
strcpy(avc->linkData, rw ? "%" : "#");
|
||||
strcat(avc->linkData, c->cellName);
|
||||
strcat(avc->linkData, ":root.cell");
|
||||
|
||||
status->UnixModeBits = 0644;
|
||||
}
|
||||
|
||||
status->FileType = SymbolicLink;
|
||||
status->LinkCount = 1;
|
||||
status->Length = linklen;
|
||||
status->DataVersion = 1;
|
||||
status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
|
||||
status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
|
||||
status->ParentVnode = 1;
|
||||
status->ParentUnique = 1;
|
||||
|
||||
afs_PutCell(c, READ_LOCK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable dynroot. Returns 0 if successful.
|
||||
*/
|
||||
int
|
||||
afs_SetDynrootEnable(enable)
|
||||
int enable;
|
||||
{
|
||||
afs_dynrootEnable = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if dynroot support is enabled.
|
||||
*/
|
||||
int
|
||||
afs_GetDynrootEnable()
|
||||
{
|
||||
return afs_dynrootEnable;
|
||||
}
|
@ -1687,8 +1687,15 @@ loop:
|
||||
/* stat the file */
|
||||
afs_RemoveVCB(afid);
|
||||
{
|
||||
struct AFSFetchStatus OutStatus;
|
||||
code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
|
||||
struct AFSFetchStatus OutStatus;
|
||||
|
||||
if (afs_DynrootNewVnode(tvc, &OutStatus)) {
|
||||
afs_ProcessFS(tvc, &OutStatus, areq);
|
||||
tvc->states |= CStatd | CUnique;
|
||||
code = 0;
|
||||
} else {
|
||||
code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
|
||||
}
|
||||
}
|
||||
|
||||
if (code) {
|
||||
|
@ -72,6 +72,7 @@ afs_int32 fvTable[NFENTRIES];
|
||||
/* Forward declarations */
|
||||
static struct volume *afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
|
||||
struct vrequest *areq, afs_int32 locktype);
|
||||
static struct volume *afs_NewDynrootVolume(struct VenusFid *fid);
|
||||
static inVolList();
|
||||
|
||||
|
||||
@ -402,8 +403,12 @@ struct volume *afs_GetVolume(afid, areq, locktype)
|
||||
|
||||
tv = afs_FindVolume(afid, locktype);
|
||||
if (!tv) {
|
||||
bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
|
||||
tv = afs_NewVolumeByName(bp, afid->Cell, 0, areq, locktype);
|
||||
if (afs_IsDynrootFid(afid)) {
|
||||
tv = afs_NewDynrootVolume(afid);
|
||||
} else {
|
||||
bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
|
||||
tv = afs_NewVolumeByName(bp, afid->Cell, 0, areq, locktype);
|
||||
}
|
||||
}
|
||||
return tv;
|
||||
} /*afs_GetVolume*/
|
||||
@ -549,6 +554,29 @@ struct volume *afs_GetVolumeByName(aname, acell, agood, areq, locktype)
|
||||
return(tv);
|
||||
}
|
||||
|
||||
static struct volume *afs_NewDynrootVolume(struct VenusFid *fid) {
|
||||
struct cell *tcell;
|
||||
struct volume *tv;
|
||||
struct vldbentry tve;
|
||||
char *bp, tbuf[CVBS];
|
||||
|
||||
tcell = afs_GetCell(fid->Cell, READ_LOCK);
|
||||
if (!tcell)
|
||||
return (struct volume *) 0;
|
||||
if (!(tcell->states & CHasVolRef))
|
||||
tcell->states |= CHasVolRef;
|
||||
|
||||
bp = afs_cv2string(&tbuf[CVBS], fid->Fid.Volume);
|
||||
memset(&tve, 0, sizeof(tve));
|
||||
strcpy(tve.name, "local-dynroot");
|
||||
tve.volumeId[ROVOL] = fid->Fid.Volume;
|
||||
tve.flags = VLF_ROEXISTS;
|
||||
|
||||
tv = afs_SetupVolume(0, bp, &tve, tcell, 0, 0, 0);
|
||||
afs_PutCell(tcell, READ_LOCK);
|
||||
return tv;
|
||||
}
|
||||
|
||||
int lastnvcode;
|
||||
static struct volume *afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
|
||||
struct vrequest *areq, afs_int32 locktype)
|
||||
|
@ -239,6 +239,7 @@ static int enable_process_stats = 0; /* enable rx stats */
|
||||
#ifdef AFS_AFSDB_ENV
|
||||
static int enable_afsdb = 0; /* enable AFSDB support */
|
||||
#endif
|
||||
static int enable_dynroot = 0; /* enable dynroot support */
|
||||
#ifdef notdef
|
||||
static int inodes = 60; /* VERY conservative, but has to be */
|
||||
#endif
|
||||
@ -1307,6 +1308,10 @@ mainproc(as, arock)
|
||||
nFilesPerDir = res;
|
||||
}
|
||||
}
|
||||
if (as->parms[26].items) {
|
||||
/* -dynroot */
|
||||
enable_dynroot = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pull out all the configuration info for the workstation's AFS cache and
|
||||
@ -1538,6 +1543,14 @@ mainproc(as, arock)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (enable_dynroot) {
|
||||
if (afsd_verbose)
|
||||
printf("%s: Enabling dynroot support in kernel.\n", rn);
|
||||
code = call_syscall(AFSOP_SET_DYNROOT, 1);
|
||||
if (code)
|
||||
printf("%s: Error enabling dynroot support.\n", rn);
|
||||
}
|
||||
|
||||
/* Initialize AFS daemon threads. */
|
||||
if (afsd_verbose)
|
||||
printf("%s: Forking AFS daemon.\n", rn);
|
||||
@ -1889,6 +1902,7 @@ char **argv; {
|
||||
#endif
|
||||
), "Enable AFSDB support");
|
||||
cmd_AddParm(ts, "-files_per_subdir", CMD_SINGLE, CMD_OPTIONAL, "log(2) of the number of cache files per cache subdirectory");
|
||||
cmd_AddParm(ts, "-dynroot", CMD_FLAG, CMD_OPTIONAL, "Enable dynroot support");
|
||||
return (cmd_Dispatch(argc, argv));
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#define AFSOP_ADDCELL2 29 /* 2nd add cell protocol interface */
|
||||
#define AFSOP_AFSDB_HANDLER 30 /* userspace AFSDB lookup handler */
|
||||
#define AFSOP_SET_DYNROOT 31 /* enable/disable dynroot support */
|
||||
|
||||
/* The range 20-30 is reserved for AFS system offsets in the afs_syscall */
|
||||
#define AFSCALL_PIOCTL 20
|
||||
|
@ -39,8 +39,8 @@ struct PageHeader
|
||||
};
|
||||
|
||||
struct DirHeader
|
||||
{/* A directory header object.
|
||||
*/struct PageHeader header;
|
||||
{/* A directory header object. */
|
||||
struct PageHeader header;
|
||||
char alloMap[MAXPAGES]; /* one byte per 2K page */
|
||||
unsigned short hashTable[NHASHENT];
|
||||
};
|
||||
|
@ -55,6 +55,7 @@ AFSAOBJS = \
|
||||
afs_daemons.o \
|
||||
afs_dcache.o \
|
||||
afs_dir.o \
|
||||
afs_dynroot.o \
|
||||
afs_init.o \
|
||||
afs_lock.o \
|
||||
afs_mariner.o \
|
||||
@ -152,6 +153,8 @@ afs_conn.o: $(AFS)/afs_conn.c
|
||||
$(CRULE2);
|
||||
afs_dcache.o: $(AFS)/afs_dcache.c
|
||||
$(CRULE2);
|
||||
afs_dynroot.o: $(AFS)/afs_dynroot.c
|
||||
$(CRULE2);
|
||||
afs_init.o: $(AFS)/afs_init.c
|
||||
$(CRULE2);
|
||||
afs_mariner.o: $(AFS)/afs_mariner.c
|
||||
|
@ -63,6 +63,7 @@ UAFSOBJ = \
|
||||
$(UOBJ)/afs_daemons.o \
|
||||
$(UOBJ)/afs_dcache.o \
|
||||
$(UOBJ)/afs_dir.o \
|
||||
$(UOBJ)/afs_dynroot.o \
|
||||
$(UOBJ)/afs_init.o \
|
||||
$(UOBJ)/afs_lock.o \
|
||||
$(UOBJ)/afs_mariner.o \
|
||||
@ -179,6 +180,7 @@ AFSWEBOBJ = \
|
||||
$(WEBOBJ)/afs_daemons.o \
|
||||
$(WEBOBJ)/afs_dcache.o \
|
||||
$(WEBOBJ)/afs_dir.o \
|
||||
$(WEBOBJ)/afs_dynroot.o \
|
||||
$(WEBOBJ)/afs_init.o \
|
||||
$(WEBOBJ)/afs_lock.o \
|
||||
$(WEBOBJ)/afs_mariner.o \
|
||||
@ -297,6 +299,7 @@ AFSWEBOBJKRB = \
|
||||
$(WEBOBJ)/afs_daemons.o \
|
||||
$(WEBOBJ)/afs_dcache.o \
|
||||
$(WEBOBJ)/afs_dir.o \
|
||||
$(WEBOBJ)/afs_dynroot.o \
|
||||
$(WEBOBJ)/afs_init.o \
|
||||
$(WEBOBJ)/afs_lock.o \
|
||||
$(WEBOBJ)/afs_mariner.o \
|
||||
@ -417,6 +420,8 @@ $(UOBJ)/afs_conn.o: $(AFS)/afs_conn.c
|
||||
$(CRULE1);
|
||||
$(UOBJ)/afs_dcache.o: $(AFS)/afs_dcache.c
|
||||
$(CRULE1);
|
||||
$(UOBJ)/afs_dynroot.o: $(AFS)/afs_dynroot.c
|
||||
$(CRULE1);
|
||||
$(UOBJ)/afs_init.o: $(AFS)/afs_init.c
|
||||
$(CRULE1);
|
||||
$(UOBJ)/afs_mariner.o: $(AFS)/afs_mariner.c
|
||||
@ -660,6 +665,8 @@ $(WEBOBJ)/afs_conn.o: $(AFS)/afs_conn.c
|
||||
$(CRULE2);
|
||||
$(WEBOBJ)/afs_dcache.o: $(AFS)/afs_dcache.c
|
||||
$(CRULE2);
|
||||
$(WEBOBJ)/afs_dynroot.o: $(AFS)/afs_dynroot.c
|
||||
$(CRULE2);
|
||||
$(WEBOBJ)/afs_init.o: $(AFS)/afs_init.c
|
||||
$(CRULE2);
|
||||
$(WEBOBJ)/afs_mariner.o: $(AFS)/afs_mariner.c
|
||||
|
Loading…
Reference in New Issue
Block a user