libafs: track dynroot locks for cmdebug
[openafs.git] / src / afs / afs_dynroot.c
index 80879c7..144a2d4 100644 (file)
@@ -54,7 +54,7 @@ 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;
@@ -74,7 +74,7 @@ struct afs_dynSymlink {
     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;
@@ -84,10 +84,10 @@ static int afs_dynSymlinkIndex = 0;
  * Set up a cell for dynroot if it's not there yet.
  */
 static int
-afs_dynrootCellInit()
+afs_dynrootCellInit(void)
 {
     if (!afs_dynrootCell) {
-       afs_int32 cellHosts[MAXCELLHOSTS];
+       afs_int32 cellHosts[AFS_MAXCELLHOSTS];
        struct cell *tc;
        int code;
 
@@ -168,19 +168,19 @@ afs_GetDynrootMountFid(struct VenusFid *fid)
 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->fid);
+    return afs_IsDynrootMountFid(&avc->f.fid);
 }
 
 int
 afs_IsDynrootAny(struct vcache *avc)
 {
-    return afs_IsDynrootAnyFid(&avc->fid);
+    return afs_IsDynrootAnyFid(&avc->f.fid);
 }
 
 /*
@@ -257,7 +257,7 @@ afs_dynroot_addDirEnt(struct DirHeader *dirHeader, int *curPageP,
     /*
      * 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);
 
@@ -295,7 +295,7 @@ afs_DynrootInvalidate(void)
        ReleaseReadLock(&afs_xvcache);
     } while (retry);
     if (tvc) {
-       tvc->states &= ~(CStatd | CUnique);
+       tvc->f.states &= ~(CStatd | CUnique);
        osi_dnlc_purgedp(tvc);
        afs_PutVCache(tvc);
     }
@@ -341,11 +341,13 @@ afs_RebuildDynroot(void)
        c = afs_GetCellByIndex(cellidx, READ_LOCK);
        if (!c)
            break;
-       if (c->cellNum == afs_dynrootCell)
+       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);
 
@@ -364,6 +366,7 @@ afs_RebuildDynroot(void)
 
        dotLen = strlen(ca->alias) + 2;
        dotCell = afs_osi_Alloc(dotLen);
+       osi_Assert(dotCell != NULL);
        strcpy(dotCell, ".");
        afs_strcat(dotCell, ca->alias);
 
@@ -384,6 +387,7 @@ afs_RebuildDynroot(void)
 
     dirSize = (curPage + 1) * AFS_PAGESIZE;
     newDir = afs_osi_Alloc(dirSize);
+    osi_Assert(newDir != NULL);
 
     /*
      * Now actually construct the directory.
@@ -403,8 +407,7 @@ afs_RebuildDynroot(void)
     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 the dynamic mount directory */
     afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
@@ -417,11 +420,14 @@ afs_RebuildDynroot(void)
        c = afs_GetCellByIndex(cellidx, READ_LOCK);
        if (!c)
            continue;
-       if (c->cellNum == afs_dynrootCell)
+       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,
@@ -441,6 +447,7 @@ afs_RebuildDynroot(void)
 
        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,
@@ -479,6 +486,7 @@ afs_RebuildDynrootMount(void)
     struct DirHeader *dirHeader;
 
     newDir = afs_osi_Alloc(AFS_PAGESIZE);
+    osi_Assert(newDir != NULL);
 
     /*
      * Now actually construct the directory.
@@ -498,8 +506,7 @@ afs_RebuildDynrootMount(void)
     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 ".." */
     afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
@@ -598,25 +605,25 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
 {
     char *bp, tbuf[CVBS];
 
-    if (_afs_IsDynrootFid(&avc->fid)) {
+    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();
-       return 1;
+       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;
@@ -632,9 +639,9 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
        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;
@@ -647,6 +654,7 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
            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;
@@ -654,21 +662,24 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
            }
            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
-           && VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) != VN_TYPE_MOUNT) {
+       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);
@@ -692,6 +703,7 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
                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);
            }
@@ -699,7 +711,7 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
            status->UnixModeBits = 0755;
            afs_PutCellAlias(ca);
 
-       } else if (VNUM_TO_VNTYPE(avc->fid.Fid.Vnode) == VN_TYPE_MOUNT) {
+       } 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",
@@ -711,9 +723,10 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
             * linkData needs to contain "%cell:volumeid"
             */
            namelen = strlen(c->cellName);
-           bp = afs_cv2string(&tbuf[CVBS], avc->fid.Fid.Unique);
+           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, ":");
@@ -737,6 +750,7 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
            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");
@@ -746,10 +760,31 @@ afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
        }
 
        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;
 }
 
 /*
@@ -760,8 +795,8 @@ afs_InitDynroot(void)
 {
     if (afs_dynrootInit)
        return 0;
-    RWLOCK_INIT(&afs_dynrootDirLock, "afs_dynrootDirLock");
-    RWLOCK_INIT(&afs_dynSymlinkLock, "afs_dynSymlinkLock");
+    AFS_RWLOCK_INIT(&afs_dynrootDirLock, "afs_dynrootDirLock");
+    AFS_RWLOCK_INIT(&afs_dynSymlinkLock, "afs_dynSymlinkLock");
     afs_dynrootInit = 0;
     return afs_dynrootCellInit();
 }
@@ -789,13 +824,17 @@ afs_GetDynrootEnable(void)
  * Remove a temporary symlink entry from /afs.
  */
 int
-afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred, char *aname)
+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);
@@ -829,12 +868,12 @@ afs_DynrootVOPRemove(struct vcache *avc, struct AFS_UCRED *acred, char *aname)
  * Create a temporary symlink entry in /afs.
  */
 int
-afs_DynrootVOPSymlink(struct vcache *avc, struct AFS_UCRED *acred,
+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;
@@ -852,11 +891,14 @@ afs_DynrootVOPSymlink(struct vcache *avc, struct AFS_UCRED *acred,
 
     /* 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);