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:
Nickolai Zeldovich 2001-10-10 01:10:29 +00:00 committed by Derrick Brashear
parent 56fa8cca37
commit 077c0a4d76
15 changed files with 652 additions and 52 deletions

9
NEWS
View File

@ -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
View File

@ -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

View File

@ -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.

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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;
}

View File

@ -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) {

View File

@ -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)

View File

@ -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));
}

View File

@ -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

View File

@ -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];
};

View File

@ -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

View File

@ -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