From b28927c75261d45872d80f32bf4e39d76eb9ac73 Mon Sep 17 00:00:00 2001 From: Nickolai Zeldovich Date: Thu, 1 Nov 2001 05:24:30 +0000 Subject: [PATCH] dynroot-allow-cell-aliases-20011101 allow cell aliases. includes support for non-'V' pioctls --- NEWS | 9 +- src/afs/IRIX/osi_vfsops.c | 2 +- src/afs/VNOPS/afs_vnop_remove.c | 4 + src/afs/VNOPS/afs_vnop_symlink.c | 4 + src/afs/afs.h | 5 +- src/afs/afs_call.c | 27 +++++ src/afs/afs_cell.c | 44 +++---- src/afs/afs_dynroot.c | 246 +++++++++++++++++++++++++++++++++------ src/afs/afs_osi_vget.c | 2 +- src/afs/afs_pioctl.c | 144 +++++++++++++++++++---- src/afsd/afsd.c | 11 ++ src/auth/cellconfig.c | 74 +++++++++++- src/auth/cellconfig.p.h | 11 ++ src/config/afs_args.h | 1 + src/config/venus.h | 5 + src/util/dirpath.c | 5 + src/util/dirpath.hin | 3 + src/util/vice.h | 3 +- src/venus/fs.c | 69 +++++++++++ 19 files changed, 586 insertions(+), 83 deletions(-) diff --git a/NEWS b/NEWS index a805cee..535c528 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,11 @@ -OpenAFS News -- history of user-visible changes. October 13, 2001 +OpenAFS News -- history of user-visible changes. October 19, 2001 + +* Changes incorporated in OpenAFS 1.2.3 + +** Cell aliases for dynroot can be specified in the CellAlias file in + /usr/vice/etc or /usr/local/etc/openafs, in format "realname alias", + one per line. They can also be managed at runtime with "fs newalias" + and "fs listaliases". * Changes incorporated in OpenAFS 1.2.2 diff --git a/src/afs/IRIX/osi_vfsops.c b/src/afs/IRIX/osi_vfsops.c index 7d3e74a..93d3bd0 100644 --- a/src/afs/IRIX/osi_vfsops.c +++ b/src/afs/IRIX/osi_vfsops.c @@ -537,7 +537,7 @@ 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); + tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK, 0 /* !refresh */); if (!tcell) { code = ENOENT; goto out; diff --git a/src/afs/VNOPS/afs_vnop_remove.c b/src/afs/VNOPS/afs_vnop_remove.c index fe2cf69..375f9cc 100644 --- a/src/afs/VNOPS/afs_vnop_remove.c +++ b/src/afs/VNOPS/afs_vnop_remove.c @@ -232,6 +232,10 @@ afs_remove(OSI_VC_ARG(adp), aname, acred) afs_Trace2(afs_iclSetp, CM_TRACE_REMOVE, ICL_TYPE_POINTER, adp, ICL_TYPE_STRING, aname); + /* Check if this is dynroot */ + if (afs_IsDynroot(adp)) + return afs_DynrootVOPRemove(adp, acred, aname); + if (code = afs_InitReq(&treq, acred)) return code; tagain: diff --git a/src/afs/VNOPS/afs_vnop_symlink.c b/src/afs/VNOPS/afs_vnop_symlink.c index 72f0d6e..64edc41 100644 --- a/src/afs/VNOPS/afs_vnop_symlink.c +++ b/src/afs/VNOPS/afs_vnop_symlink.c @@ -78,6 +78,10 @@ afs_symlink AFS_STATCNT(afs_symlink); afs_Trace2(afs_iclSetp, CM_TRACE_SYMLINK, ICL_TYPE_POINTER, adp, ICL_TYPE_STRING, aname); + + if (afs_IsDynroot(adp)) + return afs_DynrootVOPSymlink(adp, acred, aname, atargetName); + if (code = afs_InitReq(&treq, acred)) return code; diff --git a/src/afs/afs.h b/src/afs/afs.h index d37fe87..bd6bf5b 100644 --- a/src/afs/afs.h +++ b/src/afs/afs.h @@ -200,7 +200,7 @@ struct cell { short states; /* state flags */ short cellIndex; /* relative index number per cell */ time_t timeout; /* data expire time, if non-zero */ - struct cell *alias; /* what this cell is an alias for */ + char *realName; /* who this cell is an alias for */ }; #define afs_PutCell(cellp, locktype) @@ -967,6 +967,7 @@ extern struct brequest afs_brs[NBRS]; /* request structures */ extern struct cell *afs_GetCell(); extern struct cell *afs_GetCellByName(); +extern struct cell *afs_GetCellByName2(); extern struct cell *afs_GetCellByIndex(); extern struct unixuser *afs_GetUser(); extern struct volume *afs_GetVolume(); @@ -1010,6 +1011,8 @@ extern void afs_PutDynroot(); extern int afs_DynrootNewVnode(); extern int afs_SetDynrootEnable(); extern int afs_GetDynrootEnable(); +extern int afs_DynrootVOPSymlink(); +extern int afs_DynrootVOPRemove(); /* Performance hack - we could replace VerifyVCache2 with the appropriate diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c index f4e029a..8054de5 100644 --- a/src/afs/afs_call.c +++ b/src/afs/afs_call.c @@ -326,6 +326,33 @@ long parm, parm2, parm3, parm4, parm5, parm6; osi_FreeSmallSpace(tbuffer); osi_FreeSmallSpace(tbuffer1); } + else if (parm == AFSOP_ADDCELLALIAS) { + /* + * Call arguments: + * 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 */ + + osi_FreeSmallSpace(aliasName); + osi_FreeSmallSpace(cellName); + } else if (parm == AFSOP_CACHEINIT) { struct afs_cacheParams cparms; diff --git a/src/afs/afs_cell.c b/src/afs/afs_cell.c index add7e60..5870679 100644 --- a/src/afs/afs_cell.c +++ b/src/afs/afs_cell.c @@ -78,7 +78,7 @@ char afs_AfsdbHandler_ReqPending = 0; char afs_AfsdbHandler_Completed = 0; -static struct cell *afs_GetCellByName_int(); +struct cell *afs_GetCellByName2(); int afs_strcasecmp(s1, s2) register char *s1, *s2; @@ -271,7 +271,7 @@ struct cell *afs_GetCellByName_Dns(acellName, locktype) if (realName) afs_osi_Free(realName, strlen(realName) + 1); - return afs_GetCellByName_int(acellName, locktype, 0); + return afs_GetCellByName2(acellName, locktype, 0); bad: if (realName) @@ -280,15 +280,17 @@ bad: } -static struct cell *afs_GetCellByName_int(acellName, locktype, trydns) +struct cell *afs_GetCellByName2(acellName, locktype, trydns) register char *acellName; afs_int32 locktype; char trydns; { register struct cell *tc; register struct afs_q *cq, *tq; + int didAlias = 0; AFS_STATCNT(afs_GetCellByName); +retry: ObtainWriteLock(&afs_xcell,100); for (cq = CellLRU.next; cq != &CellLRU; cq = tq) { tc = QTOC(cq); tq = QNext(cq); @@ -297,9 +299,11 @@ static struct cell *afs_GetCellByName_int(acellName, locktype, trydns) QAdd(&CellLRU, &tc->lruq); ReleaseWriteLock(&afs_xcell); afs_RefreshCell(tc); - if (tc->states & CAlias) { - tc = tc->alias; - afs_RefreshCell(tc); + if ((tc->states & CAlias) && (didAlias == 0)) { + acellName = tc->realName; + if (!acellName) return (struct cell *) 0; + didAlias = 1; + goto retry; } return tc; } @@ -308,14 +312,14 @@ static struct cell *afs_GetCellByName_int(acellName, locktype, trydns) return trydns ? afs_GetCellByName_Dns(acellName, locktype) : (struct cell *) 0; -} /*afs_GetCellByName_int*/ +} /*afs_GetCellByName2*/ struct cell *afs_GetCellByName(acellName, locktype) register char *acellName; afs_int32 locktype; { - return afs_GetCellByName_int(acellName, locktype, 1); + return afs_GetCellByName2(acellName, locktype, 1); } /*afs_GetCellByName*/ @@ -346,9 +350,10 @@ struct cell *afs_GetCell(acell, locktype) } /*afs_GetCell*/ -struct cell *afs_GetCellByIndex(cellindex, locktype) +struct cell *afs_GetCellByIndex(cellindex, locktype, refresh) register afs_int32 cellindex; afs_int32 locktype; + afs_int32 refresh; { register struct cell *tc; register struct afs_q *cq, *tq; @@ -361,7 +366,7 @@ struct cell *afs_GetCellByIndex(cellindex, locktype) QRemove(&tc->lruq); QAdd(&CellLRU, &tc->lruq); ReleaseWriteLock(&afs_xcell); - afs_RefreshCell(tc); + if (refresh) afs_RefreshCell(tc); return tc; } } @@ -419,6 +424,7 @@ afs_int32 afs_NewCell(acellName, acellHosts, aflags, linkedcname, fsport, vlport } 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); @@ -464,25 +470,19 @@ 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; memset((char *)tc->cellHosts, 0, sizeof(tc->cellHosts)); if (aflags & CAlias) { - struct cell *tca = NULL; - if (!aliasFor) { code = EINVAL; goto bad; } - for (cq = CellLRU.next; cq != &CellLRU; cq = tq) { - tca = QTOC(cq); tq = QNext(cq); - if (!afs_strcasecmp(tca->cellName, aliasFor)) - break; - } - if (!tca) { - code = ENOENT; - goto bad; - } - tc->alias = tca; + 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; } diff --git a/src/afs/afs_dynroot.c b/src/afs/afs_dynroot.c index 6e42e2b..bba3d42 100644 --- a/src/afs/afs_dynroot.c +++ b/src/afs/afs_dynroot.c @@ -20,6 +20,8 @@ * afs_DynrootNewVnode * afs_SetDynrootEnable * afs_GetDynrootEnable + * afs_DynrootVOPRemove + * afs_DynrootVOPSymlink * */ @@ -41,9 +43,22 @@ #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)) +/* + * 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_SYMLINK 0x02 /* 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)) static int afs_dynrootEnable = 0; @@ -57,6 +72,20 @@ static int afs_dynrootVersion = 1; static int afs_dynrootVersionHigh = 1; /* End of variables protected by afs_dynrootDirLock */ +/* A dynamically-created symlink in a dynroot /afs */ +struct afs_dynSymlink { + struct afs_dynSymlink *next; + int index; + char *name; + char *target; +}; + +static afs_rwlock_t afs_dynSymlinkLock; +/* Start of variables protected by afs_dynSymlinkLock */ +static struct afs_dynSymlink *afs_dynSymlinkBase = NULL; +static int afs_dynSymlinkIndex = 0; +/* End of variables protected by afs_dynSymlinkLock */ + extern afs_int32 afs_cellindex; extern afs_rwlock_t afs_xvcache; @@ -178,13 +207,15 @@ afs_RefreshDynroot() int cellidx, maxcellidx, i; struct cell *c; int curChunk, curPage; - int dirSize; + int dirSize, sizeOfCurEntry; char *newDir, *dotCell; struct DirHeader *dirHeader; struct PageHeader *pageHeader; struct DirEntry *dirEntry; int doFlush = 0; int linkCount = 0; + struct afs_dynSymlink *ts; + int newCellCount; /* * Save afs_cellindex here, in case it changes between the @@ -199,9 +230,7 @@ afs_RefreshDynroot() curPage = 0; for (cellidx = 0; cellidx < maxcellidx; cellidx++) { - int sizeOfCurEntry; - - c = afs_GetCellByIndex(cellidx, READ_LOCK); + c = afs_GetCellByIndex(cellidx, READ_LOCK, 0 /* don't refresh */); if (!c) continue; sizeOfCurEntry = afs_dir_NameBlobs(c->cellName); @@ -224,6 +253,18 @@ afs_RefreshDynroot() afs_PutCell(c, READ_LOCK); } + ObtainReadLock(&afs_dynSymlinkLock); + ts = afs_dynSymlinkBase; + while (ts) { + sizeOfCurEntry = afs_dir_NameBlobs(ts->name); + if (curChunk + sizeOfCurEntry > EPP) { + curPage++; + curChunk = 1; + } + curChunk += sizeOfCurEntry; + ts = ts->next; + } + dirSize = (curPage + 1) * AFS_PAGESIZE; newDir = afs_osi_Alloc(dirSize); @@ -254,31 +295,41 @@ afs_RefreshDynroot() linkCount += 2; for (cellidx = 0; cellidx < maxcellidx; cellidx++) { - c = afs_GetCellByIndex(cellidx, READ_LOCK); + c = afs_GetCellByIndex(cellidx, READ_LOCK, 0 /* don't refresh */); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, - c->cellName, CIDXRW2VNUM(cellidx, 0)); + c->cellName, VNUM_FROM_CIDX_RW(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; + dotCell, VNUM_FROM_CIDX_RW(cellidx, 1)); + if (!(c->states & CAlias)) linkCount += 2; afs_PutCell(c, READ_LOCK); } + ts = afs_dynSymlinkBase; + while (ts) { + int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index); + afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, + ts->name, vnum); + ts = ts->next; + } + + newCellCount = maxcellidx + afs_dynSymlinkIndex; + ReleaseReadLock(&afs_dynSymlinkLock); + 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) { + if (afs_dynrootCellCount != newCellCount) { /* - * New cells added -- bump data version, invalidate vcache. + * New cells/symlinks added -- bump data version, invalidate vcache. */ - afs_dynrootCellCount = maxcellidx; + afs_dynrootCellCount = newCellCount; afs_dynrootVersion++; afs_dynrootVersionHigh = osi_Time(); doFlush = 1; @@ -376,37 +427,75 @@ afs_DynrootNewVnode(avc, status) struct cell *c; int namelen, linklen, cellidx, rw; - cellidx = VNUM2CIDX(avc->fid.Fid.Vnode); - rw = VNUM2RW(avc->fid.Fid.Vnode); + memset(status, 0, sizeof(struct AFSFetchStatus)); - c = afs_GetCellByIndex(cellidx, READ_LOCK); + 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; + + if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_SYMLINK) { + struct afs_dynSymlink *ts; + int index = VNUM_TO_VNID(avc->fid.Fid.Vnode); + + ObtainReadLock(&afs_dynSymlinkLock); + ts = afs_dynSymlinkBase; + while (ts) { + if (ts->index == index) break; + ts = ts->next; + } + + if (ts) { + linklen = strlen(ts->target); + avc->linkData = afs_osi_Alloc(linklen + 1); + strcpy(avc->linkData, ts->target); + + status->Length = linklen; + status->UnixModeBits = 0755; + } + ReleaseReadLock(&afs_dynSymlinkLock); + + return ts ? 1 : 0; + } + + if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_CELL) { + afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n", + VNUM_TO_VNTYPE(avc->fid.Fid.Vnode)); + return 0; + } + + cellidx = VNUM_TO_CIDX(avc->fid.Fid.Vnode); + rw = VNUM_TO_RW(avc->fid.Fid.Vnode); + + c = afs_GetCellByIndex(cellidx, READ_LOCK, 1 /* refresh */); if (!c) { afs_warn("dynroot vnode inconsistency, can't find cell %d\n", cellidx); return 0; } - 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; + char *realName = c->realName; - if (!tca) { - afs_warn("dynroot: alias %s missing cell alias pointer\n", + if (!realName) { + afs_warn("dynroot: alias %s missing real cell name\n", c->cellName); linklen = 7; avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, "unknown"); } else { - int namelen = strlen(tca->cellName); + int namelen = strlen(realName); linklen = rw + namelen; avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, rw ? "." : ""); - strcat(avc->linkData, tca->cellName); + strcat(avc->linkData, realName); } status->UnixModeBits = 0755; @@ -424,15 +513,7 @@ afs_DynrootNewVnode(avc, status) 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; - + status->Length = linklen; afs_PutCell(c, READ_LOCK); return 1; } @@ -459,3 +540,100 @@ afs_GetDynrootEnable() { return afs_dynrootEnable; } + +/* + * Remove a temporary symlink entry from /afs. + */ +int +afs_DynrootVOPRemove(avc, acred, aname) + 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) + return EPERM; + + ObtainWriteLock(&afs_dynSymlinkLock, 97); + tpps = &afs_dynSymlinkBase; + while (*tpps) { + tps = *tpps; + if (afs_strcasecmp(aname, tps->name) == 0) { + afs_osi_Free(tps->name, strlen(tps->name) + 1); + afs_osi_Free(tps->target, strlen(tps->target) + 1); + *tpps = tps->next; + afs_osi_Free(tps, sizeof(*tps)); + afs_dynSymlinkIndex++; + found = 1; + break; + } + tpps = &(tps->next); + } + ReleaseWriteLock(&afs_dynSymlinkLock); + if (found) { + afs_RefreshDynroot(); + 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); + return EROFS; + } else { + return ENOENT; + } +} + +/* + * Create a temporary symlink entry in /afs. + */ +int +afs_DynrootVOPSymlink(avc, acred, aname, atargetName) + struct vcache *avc; + struct AFS_UCRED *acred; + char *aname; + char *atargetName; +{ + struct afs_dynSymlink *tps; + struct cell *c; + + if (acred->cr_uid) + return EPERM; + + /* Check if it's already a cell */ + c = afs_GetCellByName2(aname, READ_LOCK, 0 /* no AFSDB */); + if (c) { + afs_PutCell(c, READ_LOCK); + return EEXIST; + } + + /* Check if it's already a symlink */ + ObtainWriteLock(&afs_dynSymlinkLock, 91); + tps = afs_dynSymlinkBase; + while (tps) { + if (afs_strcasecmp(aname, tps->name) == 0) { + ReleaseWriteLock(&afs_dynSymlinkLock); + return EEXIST; + } + tps = tps->next; + } + + /* Doesn't already exist -- go ahead and create it */ + tps = afs_osi_Alloc(sizeof(*tps)); + tps->index = afs_dynSymlinkIndex++; + tps->next = afs_dynSymlinkBase; + tps->name = afs_osi_Alloc(strlen(aname) + 1); + strcpy(tps->name, aname); + tps->target = afs_osi_Alloc(strlen(atargetName) + 1); + strcpy(tps->target, atargetName); + afs_dynSymlinkBase = tps; + ReleaseWriteLock(&afs_dynSymlinkLock); + + afs_RefreshDynroot(); + return 0; +} diff --git a/src/afs/afs_osi_vget.c b/src/afs/afs_osi_vget.c index 94ab8d9..873f24f 100644 --- a/src/afs/afs_osi_vget.c +++ b/src/afs/afs_osi_vget.c @@ -55,7 +55,7 @@ int afs_osi_vget(struct vcache **avcpp, struct fid *afidp, */ struct cell *tcell; cellindex = (Sfid.CellAndUnique >> 24) & 0xff; - tcell = afs_GetCellByIndex(cellindex, READ_LOCK); + tcell = afs_GetCellByIndex(cellindex, READ_LOCK, 0 /* don't refresh */); if (!tcell) { return ENOENT; } diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c index ebda69c..bfc89a9 100644 --- a/src/afs/afs_pioctl.c +++ b/src/afs/afs_pioctl.c @@ -66,13 +66,14 @@ static int PGetCPrefs(), PSetCPrefs(); /* client network addresses */ static int PGetInitParams(), PFlushMount(), PRxStatProc(), PRxStatPeer(); static int PGetRxkcrypt(), PSetRxkcrypt(); static int PPrefetchFromTape(), PResidencyCmd(); +static int PNewAlias(), PListAliases(); int PExportAfs(); static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp); extern struct cm_initparams cm_initParams; -static int (*(pioctlSw[]))() = { +static int (*(VpioctlSw[]))() = { PBogus, /* 0 */ PSetAcl, /* 1 */ PGetAcl, /* 2 */ @@ -141,6 +142,13 @@ static int (*(pioctlSw[]))() = { PNoop, /* 65 -- arla: break callback */ PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */ PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */ + PNoop, /* 68 -- arla: fetch stats */ +}; + +static int (*(CpioctlSw[]))() = { + PBogus, /* 0 */ + PNewAlias, /* 1 -- create new cell alias */ + PListAliases, /* 2 -- list cell aliases */ }; #define PSetClientContext 99 /* Special pioctl to setup caller's creds */ @@ -741,21 +749,6 @@ afs_syscall_pioctl(path, com, cmarg, follow) #endif AFS_STATCNT(afs_syscall_pioctl); if (follow) follow = 1; /* compat. with old venus */ -#ifndef AFS_SUN5_ENV - if (! _VALIDVICEIOCTL(com)) { - PIOCTL_FREE_CRED(); -#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) - return EINVAL; -#else /* AFS_OSF_ENV */ -#if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) - return EINVAL; -#else - setuerror(EINVAL); - return EINVAL; -#endif -#endif - } -#endif code = copyin_afs_ioctl(cmarg, &data); if (code) { PIOCTL_FREE_CRED(); @@ -1036,16 +1029,31 @@ afs_HandlePioctl(avc, acom, ablob, afollow, acred) { struct vrequest treq; register afs_int32 code; - register afs_int32 function; + register afs_int32 function, device; afs_int32 inSize, outSize; char *inData, *outData; + int (*(*pioctlSw))(); + int pioctlSwSize; afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff, ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow); AFS_STATCNT(HandlePioctl); if (code = afs_InitReq(&treq, *acred)) return code; + device = (acom & 0xff00) >> 8; + switch (device) { + case 'V': /* Original pioctl's */ + pioctlSw = VpioctlSw; + pioctlSwSize = sizeof(VpioctlSw); + break; + case 'C': /* Coordinated/common pioctl's */ + pioctlSw = CpioctlSw; + pioctlSwSize = sizeof(CpioctlSw); + break; + default: + return EINVAL; + } function = acom & 0xff; - if (function >= (sizeof(pioctlSw) / sizeof(char *))) { + if (function >= (pioctlSwSize / sizeof(char *))) { return EINVAL; /* out of range */ } inSize = ablob->in_size; @@ -1061,7 +1069,7 @@ afs_HandlePioctl(avc, acom, ablob, afollow, acred) } outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ); outSize = 0; - if (function == 3) /* PSetTokens */ + if (function == 3 && device == 'V') /* PSetTokens */ code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred); else code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred); @@ -2299,6 +2307,53 @@ static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred) return code; } +static PNewAlias(avc, afun, areq, ain, aout, ainSize, aoutSize, acred) + struct vcache *avc; + int afun; + struct vrequest *areq; + register char *ain; + char *aout; + afs_int32 ainSize; + struct AFS_UCRED *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 */ + + if (!afs_osi_suser(acred)) + return EACCES; + + aliasName = tp; + 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); + *aoutSize = 0; + return code; +} + static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize) struct vcache *avc; int afun; @@ -2321,8 +2376,12 @@ static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize) 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 (whichCell == 0) break; - if (tq == &CellLRU) tcell = 0; + tcell = 0; whichCell--; } if (tcell) { @@ -2343,6 +2402,51 @@ static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize) else return EDOM; } +static PListAliases(avc, afun, areq, ain, aout, ainSize, aoutSize) + struct vcache *avc; + int afun; + struct vrequest *areq; + char *ain, *aout; + afs_int32 ainSize; + afs_int32 *aoutSize; /* set this */ +{ + afs_int32 whichAlias; + register struct cell *tcell=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 */ + if (ainSize < sizeof(afs_int32)) + return EINVAL; + + 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) { + cp = aout; + strcpy(cp, tcell->cellName); + cp += strlen(tcell->cellName)+1; + strcpy(cp, tcell->realName); + cp += strlen(tcell->realName)+1; + *aoutSize = cp - aout; + } + ReleaseReadLock(&afs_xcell); + if (tcell) return 0; + else return EDOM; +} + static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize) struct vcache *avc; int afun; diff --git a/src/afsd/afsd.c b/src/afsd/afsd.c index 66f507a..5d4fb28 100644 --- a/src/afsd/afsd.c +++ b/src/afsd/afsd.c @@ -1058,6 +1058,16 @@ struct afsconf_dir *adir; { return 0; } +static ConfigCellAlias(aca, arock, adir) + register struct afsconf_cellalias *aca; + char *arock; + struct afsconf_dir *adir; +{ + /* push the alias into the kernel */ + call_syscall(AFSOP_ADDCELLALIAS, aca->aliasName, aca->realName); + return 0; +} + #ifdef AFS_AFSDB_ENV static AfsdbLookupHandler() { @@ -1612,6 +1622,7 @@ mainproc(as, arock) 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 diff --git a/src/auth/cellconfig.c b/src/auth/cellconfig.c index cf40e41..8e299f4 100644 --- a/src/auth/cellconfig.c +++ b/src/auth/cellconfig.c @@ -357,6 +357,7 @@ char clones[]; FILE *tf; register char *tp, *bp; register struct afsconf_entry *curEntry; + struct afsconf_aliasentry *curAlias; register afs_int32 code; afs_int32 i; char tbuffer[256], tbuf1[256]; @@ -469,7 +470,44 @@ char clones[]; curEntry->next = adir->entries; adir->entries = curEntry; } - + + /* Read in the alias list */ + strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLALIAS_FILE, NULL); + + tf = fopen(tbuffer, "r"); + while (tf) { + char *aliasPtr; + + tp = fgets(tbuffer, sizeof(tbuffer), tf); + if (!tp) break; + TrimLine(tbuffer); /* remove white space */ + + if (tbuffer[0] == '\0' || + tbuffer[0] == '\n' || + tbuffer[0] == '#') continue; /* empty line */ + + tp = tbuffer; + while (tp[0] != '\0' && tp[0] != ' ' && tp[0] != '\t') tp++; + if (tp[0] == '\0') continue; /* invalid line */ + + while (tp[0] != '\0' && (tp[0] == ' ' || tp[0] == '\t')) 0[tp++] = '\0'; + if (tp[0] == '\0') continue; /* invalid line */ + + aliasPtr = tp; + while (tp[0] != '\0' && tp[0] != ' ' && tp[0] != '\t' && + tp[0] != '\r' && tp[0] != '\n') tp++; + tp[0] = '\0'; + + curAlias = malloc(sizeof(*curAlias)); + memset(curAlias, 0, sizeof(*curAlias)); + + strcpy(curAlias->aliasInfo.aliasName, aliasPtr); + strcpy(curAlias->aliasInfo.realName, tbuffer); + + curAlias->next = adir->alias_entries; + adir->alias_entries = curAlias; + } + /* now read the fs keys, if possible */ adir->keystr = (struct afsconf_keys *) 0; afsconf_IntGetKeys(adir); @@ -545,6 +583,28 @@ char *arock; { return 0; } +/* call aproc(entry, arock, adir) for all cell aliases. + * Proc must return 0, or we'll stop early and return the code it returns + */ +afsconf_CellAliasApply(adir, aproc, arock) + struct afsconf_dir *adir; + int (*aproc)(); + char *arock; +{ + register struct afsconf_aliasentry *tde; + register afs_int32 code; + LOCK_GLOBAL_MUTEX + for(tde=adir->alias_entries; tde; tde=tde->next) { + code = (*aproc)(&tde->aliasInfo, arock, adir); + if (code) { + UNLOCK_GLOBAL_MUTEX + return code; + } + } + UNLOCK_GLOBAL_MUTEX + return 0; +} + afs_int32 afsconf_SawCell = 0; afsconf_GetExtendedCellInfo(adir, acellName, aservice, acellInfo, clones) @@ -734,6 +794,7 @@ char *aservice; char *acellName; struct afsconf_cell *acellInfo; { register struct afsconf_entry *tce; + struct afsconf_aliasentry *tcae; struct afsconf_entry *bestce; register afs_int32 i; int tservice; @@ -765,6 +826,15 @@ struct afsconf_cell *acellInfo; { UNLOCK_GLOBAL_MUTEX return 0; } + + /* Look through the list of aliases */ + for (tcae = adir->alias_entries; tcae; tcae = tcae->next) { + if (strcasecmp(tcae->aliasInfo.aliasName, tcell) == 0) { + tcell = tcae->aliasInfo.realName; + break; + } + } + for(tce=adir->entries;tce;tce=tce->next) { if (strcasecmp(tce->cellInfo.name, tcell) == 0) { /* found our cell */ @@ -797,7 +867,7 @@ struct afsconf_cell *acellInfo; { else { UNLOCK_GLOBAL_MUTEX #ifdef AFS_AFSDB_ENV - return afsconf_GetAfsdbInfo(acellName, aservice, acellInfo); + return afsconf_GetAfsdbInfo(tcell, aservice, acellInfo); #else return AFSCONF_NOTFOUND; #endif /* AFS_AFSDB_ENV */ diff --git a/src/auth/cellconfig.p.h b/src/auth/cellconfig.p.h index d5fa161..5fa71d1 100644 --- a/src/auth/cellconfig.p.h +++ b/src/auth/cellconfig.p.h @@ -69,17 +69,28 @@ struct afsconf_cell { int timeout; /* Data timeout, if non-zero */ }; +struct afsconf_cellalias { + char aliasName[MAXCELLCHARS]; + char realName[MAXCELLCHARS]; +}; + struct afsconf_entry { struct afsconf_entry *next; /* next guy in afsconf_dir */ struct afsconf_cell cellInfo; /* info for this cell */ }; +struct afsconf_aliasentry { + struct afsconf_aliasentry *next; + struct afsconf_cellalias aliasInfo; +}; + struct afsconf_dir { char *name; /* pointer to dir prefix */ char *cellName; /* cell name, if any, we're in */ struct afsconf_entry *entries; /* list of cell entries */ struct afsconf_keys *keystr; /* structure containing keys */ afs_int32 timeRead; /* time stamp of file last read */ + struct afsconf_aliasentry *alias_entries; /* cell aliases */ }; extern struct afsconf_dir *afsconf_Open(); diff --git a/src/config/afs_args.h b/src/config/afs_args.h index 93a50a9..14644a2 100644 --- a/src/config/afs_args.h +++ b/src/config/afs_args.h @@ -40,6 +40,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 */ +#define AFSOP_ADDCELLALIAS 32 /* create alias for existing cell */ /* The range 20-30 is reserved for AFS system offsets in the afs_syscall */ #define AFSCALL_PIOCTL 20 diff --git a/src/config/venus.h b/src/config/venus.h index 13f85f3..2680126 100644 --- a/src/config/venus.h +++ b/src/config/venus.h @@ -177,4 +177,9 @@ struct cm_initparams { #define VIOC_PREFETCHTAPE _VICEIOCTL(66) /* MR-AFS prefetch from tape */ #define VIOC_RESIDENCY_CMD _VICEIOCTL(67) /* generic MR-AFS cmds */ #define VIOC_STATISTICS _VICEIOCTL(68) /* arla: fetch statistics */ + +/* Coordinated 'C' pioctl's */ +#define VIOC_NEWALIAS _VICEIOCTL2('C', 1) /* create new cell alias */ +#define VIOC_GETALIAS _VICEIOCTL2('C', 2) /* get alias info */ + #endif /* AFS_VENUS_H */ diff --git a/src/util/dirpath.c b/src/util/dirpath.c index ec8374d..5e69bc4 100644 --- a/src/util/dirpath.c +++ b/src/util/dirpath.c @@ -357,12 +357,17 @@ static void initDirPathArray(void) "/NoUsrViceEtcThisCellFileOnWindows"); sprintf(dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID], "%s/%s", ntClientConfigDirShort, AFSDIR_CELLSERVDB_FILE_NTCLIENT); + strcpy(dirPathArray[AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID], + "/NoCellAliasOnWindows"); #else pathp = dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID]; AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_THISCELL_FILE); pathp = dirPathArray[AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID]; AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_CELLSERVDB_FILE); + + pathp = dirPathArray[AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID]; + AFSDIR_CLIENT_FILEPATH(pathp, AFSDIR_CLIENT_ETC_DIR, AFSDIR_CELLALIAS_FILE); #endif /* AFS_NT40_ENV */ pathp = dirPathArray[AFSDIR_CLIENT_NETINFO_FILEPATH_ID]; diff --git a/src/util/dirpath.hin b/src/util/dirpath.hin index a4efdb4..b94d8d7 100644 --- a/src/util/dirpath.hin +++ b/src/util/dirpath.hin @@ -118,6 +118,7 @@ ConstructLocalLogPath(const char *cpath, /* file names */ #define AFSDIR_THISCELL_FILE "ThisCell" #define AFSDIR_CELLSERVDB_FILE "CellServDB" +#define AFSDIR_CELLALIAS_FILE "CellAlias" #define AFSDIR_KEY_FILE "KeyFile" #define AFSDIR_ULIST_FILE "UserList" #define AFSDIR_NOAUTH_FILE "NoAuth" @@ -260,6 +261,7 @@ typedef enum afsdir_id { AFSDIR_SERVER_MIGRATE_DIRPATH_ID, AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID, AFSDIR_SERVER_BIN_FILE_DIRPATH_ID, + AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID, AFSDIR_PATHSTRING_MAX } afsdir_id_t; /* getDirPath() returns a pointer to a string from an internal array of path strings @@ -331,6 +333,7 @@ const char *getDirPath(afsdir_id_t string_id); /* client file paths */ #define AFSDIR_CLIENT_THISCELL_FILEPATH getDirPath(AFSDIR_CLIENT_THISCELL_FILEPATH_ID) #define AFSDIR_CLIENT_CELLSERVDB_FILEPATH getDirPath(AFSDIR_CLIENT_CELLSERVDB_FILEPATH_ID) +#define AFSDIR_CLIENT_CELLALIAS_FILEPATH getDirPath(AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID) #define AFSDIR_CLIENT_NETINFO_FILEPATH getDirPath(AFSDIR_CLIENT_NETINFO_FILEPATH_ID) #define AFSDIR_CLIENT_NETRESTRICT_FILEPATH getDirPath(AFSDIR_CLIENT_NETRESTRICT_FILEPATH_ID) diff --git a/src/util/vice.h b/src/util/vice.h index ad817fa..52e0e59 100644 --- a/src/util/vice.h +++ b/src/util/vice.h @@ -62,8 +62,10 @@ struct ViceIoctl { */ #if defined(KERNEL) && !defined(AFS_OSF_ENV) && !defined(AFS_ALPHA_LINUX20_ENV) #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl32)) +#define _VICEIOCTL2(dev, id) ((unsigned int ) _IOW(dev, id, struct ViceIoctl32)) #else #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl)) +#define _VICEIOCTL2(dev, id) ((unsigned int ) _IOW(dev, id, struct ViceIoctl)) #endif /* Use this macro to define up to 256 vice ioctl's. These ioctl's @@ -72,4 +74,3 @@ struct ViceIoctl { into the kernel by the normal ioctl parameter passing mechanism. */ -#define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && com <= _VICEIOCTL(255)) diff --git a/src/venus/fs.c b/src/venus/fs.c index ea197b0..dbc27cd 100644 --- a/src/venus/fs.c +++ b/src/venus/fs.c @@ -1863,6 +1863,35 @@ static ListCellsCmd(as) return 0; } +static ListAliasesCmd(as) + struct cmd_syndesc *as; +{ + afs_int32 code, i; + char *tp, *aliasName, *realName; + struct ViceIoctl blob; + + for(i=0;;i++) { + tp = space; + memcpy(tp, &i, sizeof(afs_int32)); + blob.out_size = MAXSIZE; + blob.in_size = sizeof(afs_int32); + blob.in = space; + blob.out = space; + code = pioctl(0, VIOC_GETALIAS, &blob, 1); + if (code < 0) { + if (errno == EDOM) break; /* done with the list */ + Die(errno, 0); + return 1; + } + tp = space; + aliasName = tp; + tp += strlen(aliasName) + 1; + realName = tp; + printf("Alias %s for cell %s\n", aliasName, realName); + } + return 0; +} + static NewCellCmd(as) struct cmd_syndesc *as; { @@ -1964,6 +1993,40 @@ static NewCellCmd(as) return 0; } +static NewAliasCmd(as) + struct cmd_syndesc *as; +{ + afs_int32 code; + struct ViceIoctl blob; + char *tp; + char *aliasName, *realName; + + /* Now setup and do the NEWCELL pioctl call */ + aliasName = as->parms[0].items->data; + realName = as->parms[1].items->data; + tp = space; + strcpy(tp, aliasName); + tp += strlen(aliasName) + 1; + strcpy(tp, realName); + tp += strlen(realName) + 1; + + blob.in_size = tp - space; + blob.in = space; + blob.out_size = 0; + blob.out = space; + code = pioctl(0, VIOC_NEWALIAS, &blob, 1); + if (code < 0) { + if (errno == EEXIST) { + fprintf(stderr, "%s: cell name `%s' in use by an existing cell.\n", + pn, aliasName); + } else { + Die(errno, 0); + } + return 1; + } + return 0; +} + static WhichCellCmd(as) struct cmd_syndesc *as; { @@ -2984,6 +3047,8 @@ defect 3069 ts = cmd_CreateSyntax("listcells", ListCellsCmd, 0, "list configured cells"); cmd_AddParm(ts, "-numeric", CMD_FLAG, CMD_OPTIONAL, "addresses only"); + ts = cmd_CreateSyntax("listaliases", ListAliasesCmd, 0, "list configured cell aliases"); + ts = cmd_CreateSyntax("setquota", SetQuotaCmd, 0, "set volume quota"); cmd_AddParm(ts, "-path", CMD_SINGLE, CMD_OPTIONAL, "dir/file path"); cmd_AddParm(ts, "-max", CMD_SINGLE, 0, "max quota in kbytes"); @@ -2997,6 +3062,10 @@ defect 3069 cmd_AddParm(ts, "-servers", CMD_LIST, CMD_REQUIRED, "primary servers"); cmd_AddParm(ts, "-linkedcell", CMD_SINGLE, CMD_OPTIONAL, "linked cell name"); + ts = cmd_CreateSyntax("newalias", NewAliasCmd, 0, "configure new cell alias"); + cmd_AddParm(ts, "-alias", CMD_SINGLE, 0, "alias name"); + cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "real name of cell"); + #ifdef FS_ENABLE_SERVER_DEBUG_PORTS /* * Turn this on only if you wish to be able to talk to a server which is listening -- 1.9.4