-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
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;
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:
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;
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)
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();
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
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;
char afs_AfsdbHandler_Completed = 0;
-static struct cell *afs_GetCellByName_int();
+struct cell *afs_GetCellByName2();
int afs_strcasecmp(s1, s2)
register char *s1, *s2;
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)
}
-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);
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;
}
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*/
} /*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;
QRemove(&tc->lruq);
QAdd(&CellLRU, &tc->lruq);
ReleaseWriteLock(&afs_xcell);
- afs_RefreshCell(tc);
+ if (refresh) afs_RefreshCell(tc);
return tc;
}
}
}
else {
tc = (struct cell *) afs_osi_Alloc(sizeof(struct cell));
+ memset((char *)tc, 0, sizeof(*tc));
QAdd(&CellLRU, &tc->lruq); /* put in lruq */
tc->cellName = (char *) afs_osi_Alloc(strlen(acellName)+1);
strcpy(tc->cellName, acellName);
}
tc->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;
}
* afs_DynrootNewVnode
* afs_SetDynrootEnable
* afs_GetDynrootEnable
+ * afs_DynrootVOPRemove
+ * afs_DynrootVOPSymlink
*
*/
#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;
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;
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
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);
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);
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;
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;
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;
}
{
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;
+}
*/
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;
}
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 */
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 */
#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();
{
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;
}
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);
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;
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) {
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;
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()
{
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
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];
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);
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)
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;
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 */
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 */
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();
#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
#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 */
"/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];
/* 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"
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
/* 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)
*/
#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
into the kernel by the normal ioctl parameter passing mechanism.
*/
-#define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && com <= _VICEIOCTL(255))
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;
{
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;
{
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");
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