/* * Regenerates the dynroot contents from the current list of * cells. Useful when the list of cells has changed due to * an AFSDB lookup, for instance. */ static void afs_RebuildDynroot(void) { int cellidx, maxcellidx, i; int aliasidx, maxaliasidx; struct cell *c; struct cell_alias *ca; int curChunk, curPage; int dirSize, dotLen; char *newDir, *dotCell; struct DirHeader *dirHeader; int linkCount = 0; struct afs_dynSymlink *ts; int newVersion; ObtainReadLock(&afs_dynrootDirLock); newVersion = afs_dynrootVersion; ReleaseReadLock(&afs_dynrootDirLock); /* * Compute the amount of space we need for the fake dir */ curChunk = 13; curPage = 0; /* Reserve space for "." and ".." */ curChunk += 2; /* Reserve space for the dynamic-mount directory */ afs_dynroot_computeDirEnt(AFS_DYNROOT_MOUNTNAME, &curPage, &curChunk); for (cellidx = 0;; cellidx++) { c = afs_GetCellByIndex(cellidx, READ_LOCK); if (!c) break; if (c->cellNum == afs_dynrootCell) continue; dotLen = strlen(c->cellName) + 2; dotCell = afs_osi_Alloc(dotLen); strcpy(dotCell, "."); afs_strcat(dotCell, c->cellName); afs_dynroot_computeDirEnt(c->cellName, &curPage, &curChunk); afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk); afs_osi_Free(dotCell, dotLen); afs_PutCell(c, READ_LOCK); } maxcellidx = cellidx; for (aliasidx = 0;; aliasidx++) { ca = afs_GetCellAlias(aliasidx); if (!ca) break; dotLen = strlen(ca->alias) + 2; dotCell = afs_osi_Alloc(dotLen); strcpy(dotCell, "."); afs_strcat(dotCell, ca->alias); afs_dynroot_computeDirEnt(ca->alias, &curPage, &curChunk); afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk); afs_osi_Free(dotCell, dotLen); afs_PutCellAlias(ca); } maxaliasidx = aliasidx; ObtainReadLock(&afs_dynSymlinkLock); ts = afs_dynSymlinkBase; while (ts) { afs_dynroot_computeDirEnt(ts->name, &curPage, &curChunk); ts = ts->next; } dirSize = (curPage + 1) * AFS_PAGESIZE; newDir = afs_osi_Alloc(dirSize); /* * Now actually construct the directory. */ curChunk = 13; curPage = 0; dirHeader = (struct DirHeader *)newDir; dirHeader->header.pgcount = 0; dirHeader->header.tag = htons(1234); dirHeader->header.freecount = 0; dirHeader->header.freebitmap[0] = 0xff; dirHeader->header.freebitmap[1] = 0x1f; for (i = 2; i < EPP / 8; i++) dirHeader->header.freebitmap[i] = 0; dirHeader->alloMap[0] = EPP - DHE - 1; for (i = 1; i < MAXPAGES; i++) dirHeader->alloMap[i] = EPP; for (i = 0; i < NHASHENT; i++) dirHeader->hashTable[i] = 0; /* Install ".", "..", and the dynamic mount directory */ afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, AFS_DYNROOT_MOUNTNAME, AFS_DYNROOT_MOUNT_VNODE); linkCount += 3; for (cellidx = 0; cellidx < maxcellidx; cellidx++) { c = afs_GetCellByIndex(cellidx, READ_LOCK); if (!c) continue; if (c->cellNum == afs_dynrootCell) continue; dotLen = strlen(c->cellName) + 2; dotCell = afs_osi_Alloc(dotLen); strcpy(dotCell, "."); afs_strcat(dotCell, c->cellName); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, c->cellName, VNUM_FROM_CIDX_RW(cellidx, 0)); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell, VNUM_FROM_CIDX_RW(cellidx, 1)); afs_osi_Free(dotCell, dotLen); linkCount += 2; afs_PutCell(c, READ_LOCK); } for (aliasidx = 0; aliasidx < maxaliasidx; aliasidx++) { ca = afs_GetCellAlias(aliasidx); if (!ca) continue; dotLen = strlen(ca->alias) + 2; dotCell = afs_osi_Alloc(dotLen); strcpy(dotCell, "."); afs_strcat(dotCell, ca->alias); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ca->alias, VNUM_FROM_CAIDX_RW(aliasidx, 0)); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell, VNUM_FROM_CAIDX_RW(aliasidx, 1)); afs_osi_Free(dotCell, dotLen); afs_PutCellAlias(ca); } ts = afs_dynSymlinkBase; while (ts) { int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index); afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ts->name, vnum); ts = ts->next; } 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; afs_dynrootDirVersion = newVersion; ReleaseWriteLock(&afs_dynrootDirLock); }
static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type, int (*acceptable)(void *, struct dentry *), void *context) #endif { struct VenusFid fid; struct cell *tc; struct dentry *result; #if defined(NEW_EXPORT_OPS) __u32 *fh = (__u32 *)fh_fid->raw; #endif switch (fh_type) { case AFSFH_VENUSFID: if (fh_len != 4) return NULL; fid.Cell = fh[0]; fid.Fid.Volume = fh[1]; fid.Fid.Vnode = fh[2]; fid.Fid.Unique = fh[3]; break; case AFSFH_CELLFID: if (fh_len != 7) return NULL; AFS_GLOCK(); tc = afs_GetCellByHandle((void *)fh, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return NULL; } fid.Cell = tc->cellNum; fid.Fid.Volume = fh[4]; fid.Fid.Vnode = fh[5]; fid.Fid.Unique = fh[6]; afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); break; case AFSFH_NET_VENUSFID: fid.Cell = ntohl(fh[0]); fid.Fid.Volume = ntohl(fh[1]); fid.Fid.Vnode = ntohl(fh[2]); fid.Fid.Unique = ntohl(fh[3]); break; case AFSFH_NET_CELLFID: if (fh_len != 7) return NULL; AFS_GLOCK(); tc = afs_GetCellByHandle((void *)fh, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return NULL; } fid.Cell = tc->cellNum; fid.Fid.Volume = ntohl(fh[4]); fid.Fid.Vnode = ntohl(fh[5]); fid.Fid.Unique = ntohl(fh[6]); afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); break; case AFSFH_DYN_RO_CELL: case AFSFH_DYN_RW_CELL: if (fh_len != 4) return NULL; AFS_GLOCK(); tc = afs_GetCellByHandle((void *)fh, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return NULL; } afs_GetDynrootFid(&fid); fid.Fid.Vnode = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1); fid.Fid.Unique = 1; afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); break; case AFSFH_DYN_RO_LINK: case AFSFH_DYN_RW_LINK: if (fh_len != 4) return NULL; AFS_GLOCK(); tc = afs_GetCellByHandle((void *)fh, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return NULL; } afs_GetDynrootFid(&fid); fid.Fid.Vnode = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1); fid.Fid.Unique = 1; afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); break; case AFSFH_DYN_MOUNT: if (fh_len != 5) return NULL; AFS_GLOCK(); tc = afs_GetCellByHandle((void *)fh, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return NULL; } afs_GetDynrootFid(&fid); fid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, tc->cellIndex << 2); fid.Fid.Unique = ntohl(fh[4]); afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); break; case AFSFH_DYN_SYMLINK: /* XXX parse dynroot symlink filehandle */ /* break; */ default: return NULL; } #if defined(NEW_EXPORT_OPS) result = afs_export_get_dentry(sb, &fid); #else result = sb->s_export_op->find_exported_dentry(sb, &fid, 0, acceptable, context); #endif #ifdef OSI_EXPORT_DEBUG if (!result) { printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n", fid.Cell, fid.Fid.Volume, fid.Fid.Vnode, fid.Fid.Unique); } else if (IS_ERR(result)) { printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n", fid.Cell, fid.Fid.Volume, fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result)); } #endif return result; }