2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * Dynamic /afs volume support.
15 * afs_IsDynrootMountFid
18 * afs_GetDynrootMountFid
22 * afs_DynrootInvalidate
26 * afs_SetDynrootEnable
27 * afs_GetDynrootEnable
28 * afs_DynrootVOPRemove
29 * afs_DynrootVOPSymlink
33 #include <afsconfig.h>
34 #include "afs/param.h"
37 #include "afs/sysincludes.h" /* Standard vendor system headers */
38 #include "afsincludes.h"
39 #include "afs/afs_osi.h"
43 #include "afs/prs_fs.h"
45 #include "afs/afs_dynroot.h"
47 #define AFS_DYNROOT_CELLNAME "dynroot"
48 #define AFS_DYNROOT_VOLUME 1
49 #define AFS_DYNROOT_VNODE 1
50 #define AFS_DYNROOT_MOUNT_VNODE 3
51 #define AFS_DYNROOT_UNIQUE 1
53 static int afs_dynrootInit = 0;
54 static int afs_dynrootEnable = 0;
55 static int afs_dynrootCell = 0;
57 afs_rwlock_t afs_dynrootDirLock;
58 /* Start of variables protected by afs_dynrootDirLock */
59 static char *afs_dynrootDir = NULL;
60 static int afs_dynrootDirLen;
61 static char *afs_dynrootMountDir = NULL;
62 static int afs_dynrootMountDirLen;
63 static int afs_dynrootDirLinkcnt;
64 static int afs_dynrootDirVersion;
65 static int afs_dynrootVersion = 1;
66 static int afs_dynrootVersionHigh = 1;
67 /* End of variables protected by afs_dynrootDirLock */
69 /* A dynamically-created symlink in a dynroot /afs */
70 struct afs_dynSymlink {
71 struct afs_dynSymlink *next;
77 afs_rwlock_t afs_dynSymlinkLock;
78 /* Start of variables protected by afs_dynSymlinkLock */
79 static struct afs_dynSymlink *afs_dynSymlinkBase = NULL;
80 static int afs_dynSymlinkIndex = 0;
81 /* End of variables protected by afs_dynSymlinkLock */
84 * Set up a cell for dynroot if it's not there yet.
87 afs_dynrootCellInit(void)
89 if (!afs_dynrootCell) {
90 afs_int32 cellHosts[AFS_MAXCELLHOSTS];
94 memset(cellHosts, 0, sizeof(cellHosts));
96 afs_NewCell(AFS_DYNROOT_CELLNAME, cellHosts, CNoSUID | CNoAFSDB,
100 tc = afs_GetCellByName(AFS_DYNROOT_CELLNAME, READ_LOCK);
103 afs_dynrootCell = tc->cellNum;
104 afs_PutCell(tc, READ_LOCK);
111 * Returns non-zero if the volume is the dynroot volume.
114 afs_IsDynrootVolume(struct volume *v)
116 return (afs_dynrootEnable
117 && v->cell == afs_dynrootCell
118 && v->volume == AFS_DYNROOT_VOLUME);
122 * Returns non-zero iff fid corresponds to the top of the dynroot volume.
125 _afs_IsDynrootFid(struct VenusFid *fid)
127 return (fid->Cell == afs_dynrootCell
128 && fid->Fid.Volume == AFS_DYNROOT_VOLUME
129 && fid->Fid.Vnode == AFS_DYNROOT_VNODE
130 && fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
134 afs_IsDynrootFid(struct VenusFid *fid)
136 return (afs_dynrootEnable && _afs_IsDynrootFid(fid));
140 afs_IsDynrootMountFid(struct VenusFid *fid)
142 return (fid->Cell == afs_dynrootCell
143 && fid->Fid.Volume == AFS_DYNROOT_VOLUME
144 && fid->Fid.Vnode == AFS_DYNROOT_MOUNT_VNODE
145 && fid->Fid.Unique == AFS_DYNROOT_UNIQUE);
149 afs_IsDynrootAnyFid(struct VenusFid *fid)
151 return (fid->Cell == afs_dynrootCell
152 && fid->Fid.Volume == AFS_DYNROOT_VOLUME);
156 * Obtain the magic dynroot volume Fid.
159 afs_GetDynrootFid(struct VenusFid *fid)
161 fid->Cell = afs_dynrootCell;
162 fid->Fid.Volume = AFS_DYNROOT_VOLUME;
163 fid->Fid.Vnode = AFS_DYNROOT_VNODE;
164 fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
168 afs_GetDynrootMountFid(struct VenusFid *fid)
170 fid->Cell = afs_dynrootCell;
171 fid->Fid.Volume = AFS_DYNROOT_VOLUME;
172 fid->Fid.Vnode = AFS_DYNROOT_MOUNT_VNODE;
173 fid->Fid.Unique = AFS_DYNROOT_UNIQUE;
177 * Returns non-zero iff avc is a pointer to the dynroot /afs vnode.
180 afs_IsDynroot(struct vcache *avc)
182 return afs_IsDynrootFid(&avc->f.fid);
186 afs_IsDynrootMount(struct vcache *avc)
188 return afs_IsDynrootMountFid(&avc->f.fid);
192 afs_IsDynrootAny(struct vcache *avc)
194 return afs_IsDynrootAnyFid(&avc->f.fid);
198 * Given the current page and chunk pointers in a directory, adjust them
199 * appropriately so that the given file name can be appended. Used for
200 * computing the size of a directory.
203 afs_dynroot_computeDirEnt(char *name, int *curPageP, int *curChunkP)
207 esize = afs_dir_NameBlobs(name);
208 if (*curChunkP + esize > EPP) {
216 * Add directory entry by given name to a directory. Assumes the
217 * caller has allocated the directory to be large enough to hold
218 * the necessary entry.
221 afs_dynroot_addDirEnt(struct DirHeader *dirHeader, int *curPageP,
222 int *curChunkP, char *name, int vnode)
224 char *dirBase = (char *)dirHeader;
225 struct PageHeader *pageHeader;
226 struct DirEntry *dirEntry;
227 int sizeOfEntry, i, t1, t2;
228 int curPage = *curPageP;
229 int curChunk = *curChunkP;
233 * Check if we need to flip pages.. If so, init the new page.
235 sizeOfEntry = afs_dir_NameBlobs(name);
236 if (curChunk + sizeOfEntry > EPP) {
242 pageHeader = (struct PageHeader *)(dirBase + curPage * AFS_PAGESIZE);
244 pageHeader->pgcount = 0;
245 pageHeader->tag = htons(1234);
246 pageHeader->freecount = 0;
247 pageHeader->freebitmap[0] = 0x01;
248 for (i = 1; i < EPP / 8; i++)
249 pageHeader->freebitmap[i] = 0;
251 dirHeader->alloMap[curPage] = EPP - 1;
254 dirEntry = (struct DirEntry *)(pageHeader + curChunk);
256 dirEntry->length = 0;
258 dirEntry->fid.vnode = htonl(vnode);
259 dirEntry->fid.vunique = htonl(1);
260 strcpy(dirEntry->name, name);
262 for (i = curChunk; i < curChunk + sizeOfEntry; i++) {
265 pageHeader->freebitmap[t1] |= (1 << t2);
269 * Add the new entry to the correct hash chain.
271 i = afs_dir_DirHash(name);
272 dirEntry->next = dirHeader->hashTable[i];
273 dirHeader->hashTable[i] = htons(curPage * EPP + curChunk);
275 curChunk += sizeOfEntry;
276 dirHeader->alloMap[curPage] -= sizeOfEntry;
279 *curChunkP = curChunk;
283 * Invalidate the /afs vnode for dynroot; called when the underlying
284 * directory has changed and needs to be re-read.
287 afs_DynrootInvalidate(void)
291 struct VenusFid tfid;
293 if (!afs_dynrootEnable)
296 ObtainWriteLock(&afs_dynrootDirLock, 687);
297 afs_dynrootVersion++;
298 afs_dynrootVersionHigh = osi_Time();
299 ReleaseWriteLock(&afs_dynrootDirLock);
301 afs_GetDynrootFid(&tfid);
304 ObtainReadLock(&afs_xvcache);
305 tvc = afs_FindVCache(&tfid, &retry, 0);
306 ReleaseReadLock(&afs_xvcache);
309 afs_StaleVCacheFlags(tvc, AFS_STALEVC_NOCB, CUnique);
315 * Regenerates the dynroot contents from the current list of
316 * cells. Useful when the list of cells has changed due to
317 * an AFSDB lookup, for instance.
320 afs_RebuildDynroot(void)
322 int cellidx, maxcellidx, i;
323 int aliasidx, maxaliasidx;
325 struct cell_alias *ca;
326 int curChunk, curPage;
328 char *newDir, *dotCell;
329 struct DirHeader *dirHeader;
331 struct afs_dynSymlink *ts;
334 ObtainReadLock(&afs_dynrootDirLock);
335 newVersion = afs_dynrootVersion;
336 ReleaseReadLock(&afs_dynrootDirLock);
339 * Compute the amount of space we need for the fake dir
344 /* Reserve space for "." and ".." */
347 /* Reserve space for the dynamic-mount directory */
348 afs_dynroot_computeDirEnt(AFS_DYNROOT_MOUNTNAME, &curPage, &curChunk);
350 for (cellidx = 0;; cellidx++) {
351 c = afs_GetCellByIndex(cellidx, READ_LOCK);
354 if ((c->cellNum == afs_dynrootCell) || (c->states & CHush)) {
355 afs_PutCell(c, READ_LOCK);
358 dotLen = strlen(c->cellName) + 2;
359 dotCell = afs_osi_Alloc(dotLen);
360 osi_Assert(dotCell != NULL);
361 strcpy(dotCell, ".");
362 afs_strcat(dotCell, c->cellName);
364 afs_dynroot_computeDirEnt(c->cellName, &curPage, &curChunk);
365 afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk);
367 afs_osi_Free(dotCell, dotLen);
368 afs_PutCell(c, READ_LOCK);
370 maxcellidx = cellidx;
372 for (aliasidx = 0;; aliasidx++) {
373 ca = afs_GetCellAlias(aliasidx);
377 dotLen = strlen(ca->alias) + 2;
378 dotCell = afs_osi_Alloc(dotLen);
379 osi_Assert(dotCell != NULL);
380 strcpy(dotCell, ".");
381 afs_strcat(dotCell, ca->alias);
383 afs_dynroot_computeDirEnt(ca->alias, &curPage, &curChunk);
384 afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk);
386 afs_osi_Free(dotCell, dotLen);
387 afs_PutCellAlias(ca);
389 maxaliasidx = aliasidx;
391 ObtainReadLock(&afs_dynSymlinkLock);
392 ts = afs_dynSymlinkBase;
394 afs_dynroot_computeDirEnt(ts->name, &curPage, &curChunk);
398 dirSize = (curPage + 1) * AFS_PAGESIZE;
399 newDir = afs_osi_Alloc(dirSize);
400 osi_Assert(newDir != NULL);
403 * Now actually construct the directory.
407 dirHeader = (struct DirHeader *)newDir;
409 dirHeader->header.pgcount = 0;
410 dirHeader->header.tag = htons(1234);
411 dirHeader->header.freecount = 0;
413 dirHeader->header.freebitmap[0] = 0xff;
414 dirHeader->header.freebitmap[1] = 0x1f;
415 for (i = 2; i < EPP / 8; i++)
416 dirHeader->header.freebitmap[i] = 0;
417 dirHeader->alloMap[0] = EPP - DHE - 1;
418 for (i = 1; i < MAXPAGES; i++)
419 dirHeader->alloMap[i] = EPP;
420 memset(dirHeader->hashTable, 0, NHASHENT * sizeof(dirHeader->hashTable[0]));
422 /* Install ".", "..", and the dynamic mount directory */
423 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
424 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
425 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
426 AFS_DYNROOT_MOUNTNAME, AFS_DYNROOT_MOUNT_VNODE);
429 for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
430 c = afs_GetCellByIndex(cellidx, READ_LOCK);
433 if ((c->cellNum == afs_dynrootCell) || (c->states & CHush)) {
434 afs_PutCell(c, READ_LOCK);
438 dotLen = strlen(c->cellName) + 2;
439 dotCell = afs_osi_Alloc(dotLen);
440 osi_Assert(dotCell != NULL);
441 strcpy(dotCell, ".");
442 afs_strcat(dotCell, c->cellName);
443 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, c->cellName,
444 VNUM_FROM_CIDX_RW(cellidx, 0));
445 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
446 VNUM_FROM_CIDX_RW(cellidx, 1));
447 afs_osi_Free(dotCell, dotLen);
450 afs_PutCell(c, READ_LOCK);
453 for (aliasidx = 0; aliasidx < maxaliasidx; aliasidx++) {
454 ca = afs_GetCellAlias(aliasidx);
458 dotLen = strlen(ca->alias) + 2;
459 dotCell = afs_osi_Alloc(dotLen);
460 osi_Assert(dotCell != NULL);
461 strcpy(dotCell, ".");
462 afs_strcat(dotCell, ca->alias);
463 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ca->alias,
464 VNUM_FROM_CAIDX_RW(aliasidx, 0));
465 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
466 VNUM_FROM_CAIDX_RW(aliasidx, 1));
467 afs_osi_Free(dotCell, dotLen);
468 afs_PutCellAlias(ca);
471 ts = afs_dynSymlinkBase;
473 int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index);
474 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ts->name, vnum);
478 ReleaseReadLock(&afs_dynSymlinkLock);
480 ObtainWriteLock(&afs_dynrootDirLock, 549);
482 afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
483 afs_dynrootDir = newDir;
484 afs_dynrootDirLen = dirSize;
485 afs_dynrootDirLinkcnt = linkCount;
486 afs_dynrootDirVersion = newVersion;
487 ReleaseWriteLock(&afs_dynrootDirLock);
491 afs_RebuildDynrootMount(void)
494 int curChunk, curPage;
496 struct DirHeader *dirHeader;
498 newDir = afs_osi_Alloc(AFS_PAGESIZE);
499 osi_Assert(newDir != NULL);
502 * Now actually construct the directory.
506 dirHeader = (struct DirHeader *)newDir;
508 dirHeader->header.pgcount = 0;
509 dirHeader->header.tag = htons(1234);
510 dirHeader->header.freecount = 0;
512 dirHeader->header.freebitmap[0] = 0xff;
513 dirHeader->header.freebitmap[1] = 0x1f;
514 for (i = 2; i < EPP / 8; i++)
515 dirHeader->header.freebitmap[i] = 0;
516 dirHeader->alloMap[0] = EPP - DHE - 1;
517 for (i = 1; i < MAXPAGES; i++)
518 dirHeader->alloMap[i] = EPP;
519 memset(dirHeader->hashTable, 0, NHASHENT * sizeof(dirHeader->hashTable[0]));
521 /* Install "." and ".." */
522 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
523 afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
525 ObtainWriteLock(&afs_dynrootDirLock, 549);
526 if (afs_dynrootMountDir)
527 afs_osi_Free(afs_dynrootMountDir, afs_dynrootMountDirLen);
528 afs_dynrootMountDir = newDir;
529 afs_dynrootMountDirLen = AFS_PAGESIZE;
530 ReleaseWriteLock(&afs_dynrootDirLock);
534 * Returns a pointer to the base of the dynroot directory in memory,
535 * length thereof, and a FetchStatus.
538 afs_GetDynroot(char **dynrootDir, int *dynrootLen,
539 struct AFSFetchStatus *status)
541 ObtainReadLock(&afs_dynrootDirLock);
542 if (!afs_dynrootDir || afs_dynrootDirVersion != afs_dynrootVersion) {
543 ReleaseReadLock(&afs_dynrootDirLock);
544 afs_RebuildDynroot();
545 ObtainReadLock(&afs_dynrootDirLock);
549 *dynrootDir = afs_dynrootDir;
551 *dynrootLen = afs_dynrootDirLen;
554 memset(status, 0, sizeof(struct AFSFetchStatus));
555 status->FileType = Directory;
556 status->LinkCount = afs_dynrootDirLinkcnt;
557 status->Length = afs_dynrootDirLen;
558 status->DataVersion = afs_dynrootVersion;
559 status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
560 status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
561 status->UnixModeBits = 0755;
562 status->ParentVnode = 1;
563 status->ParentUnique = 1;
564 status->dataVersionHigh = afs_dynrootVersionHigh;
569 afs_GetDynrootMount(char **dynrootDir, int *dynrootLen,
570 struct AFSFetchStatus *status)
572 ObtainReadLock(&afs_dynrootDirLock);
573 if (!afs_dynrootMountDir) {
574 ReleaseReadLock(&afs_dynrootDirLock);
575 afs_RebuildDynrootMount();
576 ObtainReadLock(&afs_dynrootDirLock);
580 *dynrootDir = afs_dynrootMountDir;
582 *dynrootLen = afs_dynrootMountDirLen;
585 memset(status, 0, sizeof(struct AFSFetchStatus));
586 status->FileType = Directory;
587 status->LinkCount = 1;
588 status->Length = afs_dynrootMountDirLen;
589 status->DataVersion = 1;
590 status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
591 status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
592 status->UnixModeBits = 0755;
593 status->ParentVnode = 1;
594 status->ParentUnique = 1;
595 status->dataVersionHigh = 0;
600 * Puts back the dynroot read lock.
605 ReleaseReadLock(&afs_dynrootDirLock);
609 * Inform dynroot that a new vnode is being created. Return value
610 * is non-zero if this vnode is handled by dynroot, in which case
611 * FetchStatus will be filled in.
614 afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
616 char *bp, tbuf[CVBS];
618 if (_afs_IsDynrootFid(&avc->f.fid)) {
619 if (!afs_dynrootEnable)
621 afs_GetDynroot(0, 0, status);
626 if (afs_IsDynrootMount(avc)) {
627 afs_GetDynrootMount(0, 0, status);
633 * Check if this is an entry under /afs, e.g. /afs/cellname.
635 if (avc->f.fid.Cell == afs_dynrootCell
636 && avc->f.fid.Fid.Volume == AFS_DYNROOT_VOLUME) {
639 struct cell_alias *ca;
640 int namelen, linklen, cellidx, rw;
642 memset(status, 0, sizeof(struct AFSFetchStatus));
644 status->FileType = SymbolicLink;
645 status->LinkCount = 1;
646 status->DataVersion = 1;
647 status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
648 status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
649 status->ParentVnode = 1;
650 status->ParentUnique = 1;
652 if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_SYMLINK) {
653 struct afs_dynSymlink *ts;
654 int index = VNUM_TO_VNID(avc->f.fid.Fid.Vnode);
656 ObtainReadLock(&afs_dynSymlinkLock);
657 ts = afs_dynSymlinkBase;
659 if (ts->index == index)
665 linklen = strlen(ts->target);
666 avc->linkData = afs_osi_Alloc(linklen + 1);
667 osi_Assert(avc->linkData != NULL);
668 strcpy(avc->linkData, ts->target);
670 status->Length = linklen;
671 status->UnixModeBits = 0755;
673 ReleaseReadLock(&afs_dynSymlinkLock);
681 if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_CELL
682 && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_ALIAS
683 && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_MOUNT) {
684 afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n",
685 VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode));
689 cellidx = VNUM_TO_CIDX(avc->f.fid.Fid.Vnode);
690 rw = VNUM_TO_RW(avc->f.fid.Fid.Vnode);
692 if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_ALIAS) {
695 ca = afs_GetCellAlias(cellidx);
697 afs_warn("dynroot vnode inconsistency, can't find alias %d\n",
703 * linkData needs to contain the name of the cell
704 * we're aliasing for.
708 afs_warn("dynroot: alias %s missing real cell name\n",
710 avc->linkData = afs_strdup("unknown");
713 int namelen = strlen(realName);
714 linklen = rw + namelen;
715 avc->linkData = afs_osi_Alloc(linklen + 1);
716 osi_Assert(avc->linkData != NULL);
717 strcpy(avc->linkData, rw ? "." : "");
718 afs_strcat(avc->linkData, realName);
721 status->UnixModeBits = 0755;
722 afs_PutCellAlias(ca);
724 } else if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
725 c = afs_GetCellByIndex(cellidx, READ_LOCK);
727 afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
733 * linkData needs to contain "%cell:volumeid"
735 namelen = strlen(c->cellName);
736 bp = afs_cv2string(&tbuf[CVBS], avc->f.fid.Fid.Unique);
737 linklen = 2 + namelen + strlen(bp);
738 avc->linkData = afs_osi_Alloc(linklen + 1);
739 osi_Assert(avc->linkData != NULL);
740 strcpy(avc->linkData, "%");
741 afs_strcat(avc->linkData, c->cellName);
742 afs_strcat(avc->linkData, ":");
743 afs_strcat(avc->linkData, bp);
745 status->UnixModeBits = 0644;
746 status->ParentVnode = AFS_DYNROOT_MOUNT_VNODE;
747 afs_PutCell(c, READ_LOCK);
750 c = afs_GetCellByIndex(cellidx, READ_LOCK);
752 afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
758 * linkData needs to contain "#cell:root.cell" or "%cell:root.cell"
760 namelen = strlen(c->cellName);
761 linklen = 1 + namelen + 10;
762 avc->linkData = afs_osi_Alloc(linklen + 1);
763 osi_Assert(avc->linkData != NULL);
764 strcpy(avc->linkData, rw ? "%" : "#");
765 afs_strcat(avc->linkData, c->cellName);
766 afs_strcat(avc->linkData, ":root.cell");
768 status->UnixModeBits = 0644;
769 afs_PutCell(c, READ_LOCK);
772 status->Length = linklen;
778 /* make sure we set type correctly when we do this. used to stay VREG */
780 switch (status->FileType) {
788 if (afs_fakestat_enable && (avc->f.m.Mode & 0111) == 0)
794 /* shouldn't happen */
801 * Make sure dynroot initialization has been done.
804 afs_InitDynroot(void)
808 AFS_RWLOCK_INIT(&afs_dynrootDirLock, "afs_dynrootDirLock");
809 AFS_RWLOCK_INIT(&afs_dynSymlinkLock, "afs_dynSymlinkLock");
811 return afs_dynrootCellInit();
815 * Enable or disable dynroot. Returns 0 if successful.
818 afs_SetDynrootEnable(int enable)
820 afs_dynrootEnable = enable;
821 return afs_InitDynroot();
825 * Check if dynroot support is enabled.
828 afs_GetDynrootEnable(void)
830 return afs_dynrootEnable;
834 * Remove a temporary symlink entry from /afs.
837 afs_DynrootVOPRemove(struct vcache *avc, afs_ucred_t *acred, char *aname)
839 struct afs_dynSymlink **tpps;
840 struct afs_dynSymlink *tps;
843 #if defined(AFS_SUN510_ENV)
844 if (crgetruid(acred))
846 if (afs_cr_uid(acred))
850 ObtainWriteLock(&afs_dynSymlinkLock, 97);
851 tpps = &afs_dynSymlinkBase;
854 if (afs_strcasecmp(aname, tps->name) == 0) {
855 afs_osi_Free(tps->name, strlen(tps->name) + 1);
856 afs_osi_Free(tps->target, strlen(tps->target) + 1);
858 afs_osi_Free(tps, sizeof(*tps));
859 afs_dynSymlinkIndex++;
865 ReleaseWriteLock(&afs_dynSymlinkLock);
867 afs_DynrootInvalidate();
871 if (afs_CellOrAliasExists(aname))
878 * Create a temporary symlink entry in /afs.
881 afs_DynrootVOPSymlink(struct vcache *avc, afs_ucred_t *acred,
882 char *aname, char *atargetName)
884 struct afs_dynSymlink *tps;
886 if (afs_cr_uid(acred))
888 if (afs_CellOrAliasExists(aname))
891 /* Check if it's already a symlink */
892 ObtainWriteLock(&afs_dynSymlinkLock, 91);
893 tps = afs_dynSymlinkBase;
895 if (afs_strcasecmp(aname, tps->name) == 0) {
896 ReleaseWriteLock(&afs_dynSymlinkLock);
902 /* Doesn't already exist -- go ahead and create it */
903 tps = afs_osi_Alloc(sizeof(*tps));
904 osi_Assert(tps != NULL);
905 tps->index = afs_dynSymlinkIndex++;
906 tps->next = afs_dynSymlinkBase;
907 tps->name = afs_osi_Alloc(strlen(aname) + 1);
908 osi_Assert(tps->name != NULL);
909 strcpy(tps->name, aname);
910 tps->target = afs_osi_Alloc(strlen(atargetName) + 1);
911 osi_Assert(tps->target != NULL);
912 strcpy(tps->target, atargetName);
913 afs_dynSymlinkBase = tps;
914 ReleaseWriteLock(&afs_dynSymlinkLock);
916 afs_DynrootInvalidate();