*
* Implements:
* afs_IsDynrootFid
+ * afs_IsDynrootMountFid
+ * afs_IsDynrootAnyFid
* afs_GetDynrootFid
+ * afs_GetDynrootMountFid
* afs_IsDynroot
+ * afs_IsDynrootMount
+ * afs_IsDynrootAny
* afs_DynrootInvalidate
* afs_GetDynroot
* afs_PutDynroot
#include "afs/param.h"
#include "afs/stds.h"
-#include "afs/sysincludes.h" /* Standard vendor system headers */
+#include "afs/sysincludes.h" /* Standard vendor system headers */
#include "afsincludes.h"
#include "afs/afs_osi.h"
#include "afsint.h"
#include "afs/prs_fs.h"
#include "afs/dir.h"
+#include "afs/afs_dynroot.h"
#define AFS_DYNROOT_CELLNAME "dynroot"
#define AFS_DYNROOT_VOLUME 1
#define AFS_DYNROOT_VNODE 1
+#define AFS_DYNROOT_MOUNT_VNODE 3
#define AFS_DYNROOT_UNIQUE 1
-/*
- * Vnode numbers in dynroot are composed of a type field (upper 8 bits)
- * and a type-specific identifier in the lower 24 bits.
- */
-#define VN_TYPE_CELL 0x01 /* Corresponds to a struct cell */
-#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_TYPEID(type, id) \
- ((type) << 24 | (id))
-#define VNUM_TO_CIDX(vnum) (VNUM_TO_VNID(vnum) >> 2)
-#define VNUM_TO_RW(vnum) (VNUM_TO_VNID(vnum) >> 1 & 1)
-#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_dynrootInit = 0;
static int afs_dynrootEnable = 0;
static int afs_dynrootCell = 0;
-static afs_rwlock_t afs_dynrootDirLock;
+afs_rwlock_t afs_dynrootDirLock;
/* Start of variables protected by afs_dynrootDirLock */
static char *afs_dynrootDir = NULL;
static int afs_dynrootDirLen;
+static char *afs_dynrootMountDir = NULL;
+static int afs_dynrootMountDirLen;
static int afs_dynrootDirLinkcnt;
static int afs_dynrootDirVersion;
static int afs_dynrootVersion = 1;
char *target;
};
-static afs_rwlock_t afs_dynSymlinkLock;
+afs_rwlock_t afs_dynSymlinkLock;
/* Start of variables protected by afs_dynSymlinkLock */
static struct afs_dynSymlink *afs_dynSymlinkBase = NULL;
static int afs_dynSymlinkIndex = 0;
/*
* Set up a cell for dynroot if it's not there yet.
*/
-static int afs_dynrootCellInit()
+static int
+afs_dynrootCellInit(void)
{
- if (afs_dynrootEnable && !afs_dynrootCell) {
- afs_int32 cellHosts[MAXCELLHOSTS];
+ if (!afs_dynrootCell) {
+ afs_int32 cellHosts[AFS_MAXCELLHOSTS];
struct cell *tc;
int code;
memset(cellHosts, 0, sizeof(cellHosts));
- code = afs_NewCell(AFS_DYNROOT_CELLNAME, cellHosts, CNoSUID | CNoAFSDB,
- NULL, 0, 0, 0);
+ 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);
/*
* Returns non-zero iff fid corresponds to the top of the dynroot volume.
*/
-int afs_IsDynrootFid(struct VenusFid *fid)
+static int
+_afs_IsDynrootFid(struct VenusFid *fid)
+{
+ return (fid->Cell == afs_dynrootCell
+ && fid->Fid.Volume == AFS_DYNROOT_VOLUME
+ && fid->Fid.Vnode == AFS_DYNROOT_VNODE
+ && fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
+}
+
+int
+afs_IsDynrootFid(struct VenusFid *fid)
+{
+ return (afs_dynrootEnable && _afs_IsDynrootFid(fid));
+}
+
+int
+afs_IsDynrootMountFid(struct VenusFid *fid)
{
- return
- (afs_dynrootEnable &&
- fid->Cell == afs_dynrootCell &&
- fid->Fid.Volume == AFS_DYNROOT_VOLUME &&
- fid->Fid.Vnode == AFS_DYNROOT_VNODE &&
- fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
+ return (fid->Cell == afs_dynrootCell
+ && fid->Fid.Volume == AFS_DYNROOT_VOLUME
+ && fid->Fid.Vnode == AFS_DYNROOT_MOUNT_VNODE
+ && fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
+}
+
+int
+afs_IsDynrootAnyFid(struct VenusFid *fid)
+{
+ return (fid->Cell == afs_dynrootCell
+ && fid->Fid.Volume == AFS_DYNROOT_VOLUME);
}
/*
* Obtain the magic dynroot volume Fid.
*/
-void afs_GetDynrootFid(struct VenusFid *fid)
+void
+afs_GetDynrootFid(struct VenusFid *fid)
{
- fid->Cell = afs_dynrootCell;
+ fid->Cell = afs_dynrootCell;
fid->Fid.Volume = AFS_DYNROOT_VOLUME;
- fid->Fid.Vnode = AFS_DYNROOT_VNODE;
+ fid->Fid.Vnode = AFS_DYNROOT_VNODE;
+ fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
+}
+
+void
+afs_GetDynrootMountFid(struct VenusFid *fid)
+{
+ fid->Cell = afs_dynrootCell;
+ fid->Fid.Volume = AFS_DYNROOT_VOLUME;
+ fid->Fid.Vnode = AFS_DYNROOT_MOUNT_VNODE;
fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
}
/*
* Returns non-zero iff avc is a pointer to the dynroot /afs vnode.
*/
-int afs_IsDynroot(struct vcache *avc)
+int
+afs_IsDynroot(struct vcache *avc)
{
- return afs_IsDynrootFid(&avc->fid);
+ return afs_IsDynrootFid(&avc->f.fid);
+}
+
+int
+afs_IsDynrootMount(struct vcache *avc)
+{
+ return afs_IsDynrootMountFid(&avc->f.fid);
+}
+
+int
+afs_IsDynrootAny(struct vcache *avc)
+{
+ return afs_IsDynrootAnyFid(&avc->f.fid);
}
/*
* appropriately so that the given file name can be appended. Used for
* computing the size of a directory.
*/
-static void afs_dynroot_computeDirEnt(char *name, int *curPageP, int *curChunkP)
+static void
+afs_dynroot_computeDirEnt(char *name, int *curPageP, int *curChunkP)
{
int esize;
* caller has allocated the directory to be large enough to hold
* the necessary entry.
*/
-static void afs_dynroot_addDirEnt(struct DirHeader *dirHeader,
- int *curPageP, int *curChunkP, char *name, int vnode)
+static void
+afs_dynroot_addDirEnt(struct DirHeader *dirHeader, int *curPageP,
+ int *curChunkP, char *name, int vnode)
{
- char *dirBase = (char *) dirHeader;
+ char *dirBase = (char *)dirHeader;
struct PageHeader *pageHeader;
struct DirEntry *dirEntry;
int sizeOfEntry, i, t1, t2;
didNewPage = 1;
}
- pageHeader = (struct PageHeader *) (dirBase + curPage * AFS_PAGESIZE);
+ 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++)
+ 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 = (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);
/*
* Add the new entry to the correct hash chain.
*/
- i = DirHash(name);
+ i = afs_dir_DirHash(name);
dirEntry->next = dirHeader->hashTable[i];
dirHeader->hashTable[i] = htons(curPage * EPP + curChunk);
* Invalidate the /afs vnode for dynroot; called when the underlying
* directory has changed and needs to be re-read.
*/
-void afs_DynrootInvalidate(void)
+void
+afs_DynrootInvalidate(void)
{
afs_int32 retry;
struct vcache *tvc;
ReleaseReadLock(&afs_xvcache);
} while (retry);
if (tvc) {
- tvc->states &= ~(CStatd | CUnique);
+ tvc->f.states &= ~(CStatd | CUnique);
osi_dnlc_purgedp(tvc);
afs_PutVCache(tvc);
}
* cells. Useful when the list of cells has changed due to
* an AFSDB lookup, for instance.
*/
-static void afs_RebuildDynroot(void)
+static void
+afs_RebuildDynroot(void)
{
int cellidx, maxcellidx, i;
int aliasidx, maxaliasidx;
/* Reserve space for "." and ".." */
curChunk += 2;
- for (cellidx = 0; ; cellidx++) {
- c = afs_GetCellByIndex(cellidx, READ_LOCK);
- if (!c) break;
- if (c->cellNum == afs_dynrootCell) continue;
+ /* Reserve space for the dynamic-mount directory */
+ afs_dynroot_computeDirEnt(AFS_DYNROOT_MOUNTNAME, &curPage, &curChunk);
+ for (cellidx = 0;; cellidx++) {
+ c = afs_GetCellByIndex(cellidx, READ_LOCK);
+ if (!c)
+ break;
+ if ((c->cellNum == afs_dynrootCell) || (c->states & CHush)) {
+ afs_PutCell(c, READ_LOCK);
+ continue;
+ }
dotLen = strlen(c->cellName) + 2;
dotCell = afs_osi_Alloc(dotLen);
+ osi_Assert(dotCell != NULL);
strcpy(dotCell, ".");
afs_strcat(dotCell, c->cellName);
}
maxcellidx = cellidx;
- for (aliasidx = 0; ; aliasidx++) {
+ for (aliasidx = 0;; aliasidx++) {
ca = afs_GetCellAlias(aliasidx);
- if (!ca) break;
+ if (!ca)
+ break;
dotLen = strlen(ca->alias) + 2;
dotCell = afs_osi_Alloc(dotLen);
+ osi_Assert(dotCell != NULL);
strcpy(dotCell, ".");
afs_strcat(dotCell, ca->alias);
dirSize = (curPage + 1) * AFS_PAGESIZE;
newDir = afs_osi_Alloc(dirSize);
+ osi_Assert(newDir != NULL);
/*
* Now actually construct the directory.
*/
curChunk = 13;
curPage = 0;
- dirHeader = (struct DirHeader *) newDir;
+ dirHeader = (struct DirHeader *)newDir;
dirHeader->header.pgcount = 0;
dirHeader->header.tag = htons(1234);
dirHeader->header.freebitmap[0] = 0xff;
dirHeader->header.freebitmap[1] = 0x1f;
- for (i = 2; i < EPP/8; i++)
+ 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;
+ memset(dirHeader->hashTable, 0, NHASHENT * sizeof(dirHeader->hashTable[0]));
- /* Install "." and ".." */
+ /* Install ".", "..", and the dynamic mount directory */
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
- linkCount += 2;
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
+ AFS_DYNROOT_MOUNTNAME, AFS_DYNROOT_MOUNT_VNODE);
+ linkCount += 3;
for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
c = afs_GetCellByIndex(cellidx, READ_LOCK);
- if (!c) continue;
- if (c->cellNum == afs_dynrootCell) continue;
+ if (!c)
+ continue;
+ if ((c->cellNum == afs_dynrootCell) || (c->states & CHush)) {
+ afs_PutCell(c, READ_LOCK);
+ continue;
+ }
dotLen = strlen(c->cellName) + 2;
dotCell = afs_osi_Alloc(dotLen);
+ osi_Assert(dotCell != NULL);
strcpy(dotCell, ".");
afs_strcat(dotCell, c->cellName);
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
- c->cellName, VNUM_FROM_CIDX_RW(cellidx, 0));
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
- dotCell, VNUM_FROM_CIDX_RW(cellidx, 1));
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, c->cellName,
+ VNUM_FROM_CIDX_RW(cellidx, 0));
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
+ VNUM_FROM_CIDX_RW(cellidx, 1));
afs_osi_Free(dotCell, dotLen);
linkCount += 2;
for (aliasidx = 0; aliasidx < maxaliasidx; aliasidx++) {
ca = afs_GetCellAlias(aliasidx);
- if (!ca) continue;
+ if (!ca)
+ continue;
dotLen = strlen(ca->alias) + 2;
dotCell = afs_osi_Alloc(dotLen);
+ osi_Assert(dotCell != NULL);
strcpy(dotCell, ".");
afs_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_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_osi_Free(dotCell, dotLen);
afs_PutCellAlias(ca);
}
ts = afs_dynSymlinkBase;
while (ts) {
int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index);
- afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
- ts->name, vnum);
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ts->name, vnum);
ts = ts->next;
}
ReleaseReadLock(&afs_dynSymlinkLock);
ObtainWriteLock(&afs_dynrootDirLock, 549);
- if (afs_dynrootDir) afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
+ if (afs_dynrootDir)
+ afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
afs_dynrootDir = newDir;
afs_dynrootDirLen = dirSize;
afs_dynrootDirLinkcnt = linkCount;
ReleaseWriteLock(&afs_dynrootDirLock);
}
+static void
+afs_RebuildDynrootMount(void)
+{
+ int i;
+ int curChunk, curPage;
+ char *newDir;
+ struct DirHeader *dirHeader;
+
+ newDir = afs_osi_Alloc(AFS_PAGESIZE);
+ osi_Assert(newDir != NULL);
+
+ /*
+ * 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;
+ memset(dirHeader->hashTable, 0, NHASHENT * sizeof(dirHeader->hashTable[0]));
+
+ /* Install "." and ".." */
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
+ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
+
+ ObtainWriteLock(&afs_dynrootDirLock, 549);
+ if (afs_dynrootMountDir)
+ afs_osi_Free(afs_dynrootMountDir, afs_dynrootMountDirLen);
+ afs_dynrootMountDir = newDir;
+ afs_dynrootMountDirLen = AFS_PAGESIZE;
+ ReleaseWriteLock(&afs_dynrootDirLock);
+}
+
/*
* Returns a pointer to the base of the dynroot directory in memory,
* length thereof, and a FetchStatus.
*/
-void afs_GetDynroot(char **dynrootDir, int *dynrootLen,
- struct AFSFetchStatus *status)
+void
+afs_GetDynroot(char **dynrootDir, int *dynrootLen,
+ struct AFSFetchStatus *status)
{
ObtainReadLock(&afs_dynrootDirLock);
if (!afs_dynrootDir || afs_dynrootDirVersion != afs_dynrootVersion) {
ObtainReadLock(&afs_dynrootDirLock);
}
- if (dynrootDir) *dynrootDir = afs_dynrootDir;
- if (dynrootLen) *dynrootLen = afs_dynrootDirLen;
+ 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->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->UnixModeBits = 0755;
+ status->ParentVnode = 1;
+ status->ParentUnique = 1;
status->dataVersionHigh = afs_dynrootVersionHigh;
}
}
+void
+afs_GetDynrootMount(char **dynrootDir, int *dynrootLen,
+ struct AFSFetchStatus *status)
+{
+ ObtainReadLock(&afs_dynrootDirLock);
+ if (!afs_dynrootMountDir) {
+ ReleaseReadLock(&afs_dynrootDirLock);
+ afs_RebuildDynrootMount();
+ ObtainReadLock(&afs_dynrootDirLock);
+ }
+
+ if (dynrootDir)
+ *dynrootDir = afs_dynrootMountDir;
+ if (dynrootLen)
+ *dynrootLen = afs_dynrootMountDirLen;
+
+ if (status) {
+ memset(status, 0, sizeof(struct AFSFetchStatus));
+ status->FileType = Directory;
+ status->LinkCount = 1;
+ status->Length = afs_dynrootMountDirLen;
+ status->DataVersion = 1;
+ status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
+ status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
+ status->UnixModeBits = 0755;
+ status->ParentVnode = 1;
+ status->ParentUnique = 1;
+ status->dataVersionHigh = 0;
+ }
+}
+
/*
* Puts back the dynroot read lock.
*/
-void afs_PutDynroot(void)
+void
+afs_PutDynroot(void)
{
ReleaseReadLock(&afs_dynrootDirLock);
}
* is non-zero if this vnode is handled by dynroot, in which case
* FetchStatus will be filled in.
*/
-int afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
+int
+afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
{
- if (!afs_dynrootEnable) return 0;
+ char *bp, tbuf[CVBS];
- if (afs_IsDynroot(avc)) {
+ if (_afs_IsDynrootFid(&avc->f.fid)) {
+ if (!afs_dynrootEnable)
+ return 0;
afs_GetDynroot(0, 0, status);
afs_PutDynroot();
- return 1;
+ goto succeed;
+ }
+
+ if (afs_IsDynrootMount(avc)) {
+ afs_GetDynrootMount(0, 0, status);
+ afs_PutDynroot();
+ goto succeed;
}
/*
* Check if this is an entry under /afs, e.g. /afs/cellname.
*/
- if (avc->fid.Cell == afs_dynrootCell &&
- avc->fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
+ if (avc->f.fid.Cell == afs_dynrootCell
+ && avc->f.fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
struct cell *c;
struct cell_alias *ca;
memset(status, 0, sizeof(struct AFSFetchStatus));
- status->FileType = SymbolicLink;
- status->LinkCount = 1;
- status->DataVersion = 1;
- status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
+ status->FileType = SymbolicLink;
+ status->LinkCount = 1;
+ status->DataVersion = 1;
+ status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
- status->ParentVnode = 1;
- status->ParentUnique = 1;
+ status->ParentVnode = 1;
+ status->ParentUnique = 1;
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_SYMLINK) {
+ if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_SYMLINK) {
struct afs_dynSymlink *ts;
- int index = VNUM_TO_VNID(avc->fid.Fid.Vnode);
+ int index = VNUM_TO_VNID(avc->f.fid.Fid.Vnode);
ObtainReadLock(&afs_dynSymlinkLock);
ts = afs_dynSymlinkBase;
while (ts) {
- if (ts->index == index) break;
+ if (ts->index == index)
+ break;
ts = ts->next;
}
if (ts) {
linklen = strlen(ts->target);
avc->linkData = afs_osi_Alloc(linklen + 1);
+ osi_Assert(avc->linkData != NULL);
strcpy(avc->linkData, ts->target);
- status->Length = linklen;
+ status->Length = linklen;
status->UnixModeBits = 0755;
}
ReleaseReadLock(&afs_dynSymlinkLock);
- return ts ? 1 : 0;
+ if (ts)
+ goto succeed;
+
+ return 0;
}
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_CELL &&
- VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_ALIAS) {
+ if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_CELL
+ && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_ALIAS
+ && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_MOUNT) {
afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n",
- VNUM_TO_VNTYPE(avc->fid.Fid.Vnode));
+ VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode));
return 0;
}
- cellidx = VNUM_TO_CIDX(avc->fid.Fid.Vnode);
- rw = VNUM_TO_RW(avc->fid.Fid.Vnode);
+ cellidx = VNUM_TO_CIDX(avc->f.fid.Fid.Vnode);
+ rw = VNUM_TO_RW(avc->f.fid.Fid.Vnode);
- if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_ALIAS) {
+ if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_ALIAS) {
char *realName;
ca = afs_GetCellAlias(cellidx);
int namelen = strlen(realName);
linklen = rw + namelen;
avc->linkData = afs_osi_Alloc(linklen + 1);
+ osi_Assert(avc->linkData != NULL);
strcpy(avc->linkData, rw ? "." : "");
afs_strcat(avc->linkData, realName);
}
status->UnixModeBits = 0755;
afs_PutCellAlias(ca);
+
+ } else if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
+ 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:volumeid"
+ */
+ namelen = strlen(c->cellName);
+ bp = afs_cv2string(&tbuf[CVBS], avc->f.fid.Fid.Unique);
+ linklen = 2 + namelen + strlen(bp);
+ avc->linkData = afs_osi_Alloc(linklen + 1);
+ osi_Assert(avc->linkData != NULL);
+ strcpy(avc->linkData, "%");
+ afs_strcat(avc->linkData, c->cellName);
+ afs_strcat(avc->linkData, ":");
+ afs_strcat(avc->linkData, bp);
+
+ status->UnixModeBits = 0644;
+ status->ParentVnode = AFS_DYNROOT_MOUNT_VNODE;
+ afs_PutCell(c, READ_LOCK);
+
} else {
c = afs_GetCellByIndex(cellidx, READ_LOCK);
if (!c) {
namelen = strlen(c->cellName);
linklen = 1 + namelen + 10;
avc->linkData = afs_osi_Alloc(linklen + 1);
+ osi_Assert(avc->linkData != NULL);
strcpy(avc->linkData, rw ? "%" : "#");
afs_strcat(avc->linkData, c->cellName);
afs_strcat(avc->linkData, ":root.cell");
}
status->Length = linklen;
- return 1;
+ goto succeed;
}
return 0;
+
+ /* make sure we set type correctly when we do this. used to stay VREG */
+ succeed:
+ switch (status->FileType) {
+ case File:
+ vSetType(avc, VREG);
+ break;
+ case Directory:
+ vSetType(avc, VDIR);
+ break;
+ case SymbolicLink:
+ if (afs_fakestat_enable && (avc->f.m.Mode & 0111) == 0)
+ vSetType(avc, VDIR);
+ else
+ vSetType(avc, VLNK);
+ break;
+ default:
+ /* shouldn't happen */
+ ;
+ }
+ return 1;
+}
+
+/*
+ * Make sure dynroot initialization has been done.
+ */
+int
+afs_InitDynroot(void)
+{
+ if (afs_dynrootInit)
+ return 0;
+ AFS_RWLOCK_INIT(&afs_dynrootDirLock, "afs_dynrootDirLock");
+ AFS_RWLOCK_INIT(&afs_dynSymlinkLock, "afs_dynSymlinkLock");
+ afs_dynrootInit = 0;
+ return afs_dynrootCellInit();
}
/*
* Enable or disable dynroot. Returns 0 if successful.
*/
-int afs_SetDynrootEnable(int enable)
+int
+afs_SetDynrootEnable(int enable)
{
afs_dynrootEnable = enable;
- return afs_dynrootCellInit();
+ return afs_InitDynroot();
}
/*
* Check if dynroot support is enabled.
*/
-int afs_GetDynrootEnable(void)
+int
+afs_GetDynrootEnable(void)
{
return afs_dynrootEnable;
}
/*
* Remove a temporary symlink entry from /afs.
*/
-int afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred,
- char *aname)
+int
+afs_DynrootVOPRemove(struct vcache *avc, afs_ucred_t *acred, char *aname)
{
struct afs_dynSymlink **tpps;
struct afs_dynSymlink *tps;
int found = 0;
- if (acred->cr_uid)
+#if defined(AFS_SUN510_ENV)
+ if (crgetruid(acred))
+#else
+ if (afs_cr_uid(acred))
+#endif
return EPERM;
ObtainWriteLock(&afs_dynSymlinkLock, 97);
/*
* Create a temporary symlink entry in /afs.
*/
-int afs_DynrootVOPSymlink(struct vcache *avc, struct AFS_UCRED *acred,
- char *aname, char *atargetName)
+int
+afs_DynrootVOPSymlink(struct vcache *avc, afs_ucred_t *acred,
+ char *aname, char *atargetName)
{
struct afs_dynSymlink *tps;
- if (acred->cr_uid)
+ if (afs_cr_uid(acred))
return EPERM;
if (afs_CellOrAliasExists(aname))
return EEXIST;
/* Doesn't already exist -- go ahead and create it */
tps = afs_osi_Alloc(sizeof(*tps));
+ osi_Assert(tps != NULL);
tps->index = afs_dynSymlinkIndex++;
tps->next = afs_dynSymlinkBase;
tps->name = afs_osi_Alloc(strlen(aname) + 1);
+ osi_Assert(tps->name != NULL);
strcpy(tps->name, aname);
tps->target = afs_osi_Alloc(strlen(atargetName) + 1);
+ osi_Assert(tps->target != NULL);
strcpy(tps->target, atargetName);
afs_dynSymlinkBase = tps;
ReleaseWriteLock(&afs_dynSymlinkLock);