int SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index, char **a_name, serverList * a_hosts) { afs_int32 i, j = 0; struct cell *tcell; char *t_name, *p_name = NULL; RX_AFS_GLOCK(); AFS_STATCNT(SRXAFSCB_GetCellServDB); tcell = afs_GetCellByIndex(a_index, READ_LOCK); if (!tcell) { i = 0; a_hosts->serverList_val = 0; a_hosts->serverList_len = 0; } else { p_name = tcell->cellName; for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++); i = strlen(p_name); a_hosts->serverList_val = afs_osi_Alloc(j * sizeof(afs_int32)); osi_Assert(a_hosts->serverList_val != NULL); a_hosts->serverList_len = j; for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++) a_hosts->serverList_val[j] = ntohl(tcell->cellHosts[j]->addr->sa_ip); afs_PutCell(tcell, READ_LOCK); } t_name = afs_osi_Alloc(i + 1); if (t_name == NULL) { afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32))); RX_AFS_GUNLOCK(); return ENOMEM; } t_name[i] = '\0'; if (p_name) memcpy(t_name, p_name, i); RX_AFS_GUNLOCK(); *a_name = t_name; return 0; }
/* * Inform dynroot that a new vnode is being created. Return value * is non-zero if this vnode is handled by dynroot, in which case * FetchStatus will be filled in. */ int afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status) { char *bp, tbuf[CVBS]; if (_afs_IsDynrootFid(&avc->f.fid)) { if (!afs_dynrootEnable) return 0; afs_GetDynroot(0, 0, status); afs_PutDynroot(); return 1; } if (afs_IsDynrootMount(avc)) { afs_GetDynrootMount(0, 0, status); afs_PutDynroot(); return 1; } /* * Check if this is an entry under /afs, e.g. /afs/cellname. */ if (avc->f.fid.Cell == afs_dynrootCell && avc->f.fid.Fid.Volume == AFS_DYNROOT_VOLUME) { struct cell *c; struct cell_alias *ca; int namelen, linklen, cellidx, rw; memset(status, 0, sizeof(struct AFSFetchStatus)); 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->f.fid.Fid.Vnode) == VN_TYPE_SYMLINK) { struct afs_dynSymlink *ts; int index = VNUM_TO_VNID(avc->f.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->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->f.fid.Fid.Vnode)); return 0; } cellidx = VNUM_TO_CIDX(avc->f.fid.Fid.Vnode); rw = VNUM_TO_RW(avc->f.fid.Fid.Vnode); if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_ALIAS) { char *realName; ca = afs_GetCellAlias(cellidx); if (!ca) { afs_warn("dynroot vnode inconsistency, can't find alias %d\n", cellidx); return 0; } /* * linkData needs to contain the name of the cell * we're aliasing for. */ realName = ca->cell; if (!realName) { afs_warn("dynroot: alias %s missing real cell name\n", ca->alias); avc->linkData = afs_strdup("unknown"); linklen = 7; } else { int namelen = strlen(realName); linklen = rw + namelen; avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, rw ? "." : ""); afs_strcat(avc->linkData, realName); } status->UnixModeBits = 0755; afs_PutCellAlias(ca); } 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", cellidx); return 0; } /* * linkData needs to contain "%cell:volumeid" */ namelen = strlen(c->cellName); bp = afs_cv2string(&tbuf[CVBS], avc->f.fid.Fid.Unique); linklen = 2 + namelen + strlen(bp); avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, "%"); afs_strcat(avc->linkData, c->cellName); afs_strcat(avc->linkData, ":"); afs_strcat(avc->linkData, bp); status->UnixModeBits = 0644; status->ParentVnode = AFS_DYNROOT_MOUNT_VNODE; afs_PutCell(c, READ_LOCK); } else { c = afs_GetCellByIndex(cellidx, READ_LOCK); if (!c) { afs_warn("dynroot vnode inconsistency, can't find cell %d\n", cellidx); return 0; } /* * linkData needs to contain "#cell:root.cell" or "%cell:root.cell" */ namelen = strlen(c->cellName); linklen = 1 + namelen + 10; avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, rw ? "%" : "#"); afs_strcat(avc->linkData, c->cellName); afs_strcat(avc->linkData, ":root.cell"); status->UnixModeBits = 0644; afs_PutCell(c, READ_LOCK); } status->Length = linklen; return 1; } return 0; }
/* * 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 int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len, int connectable) { struct vcache *tvc; struct cell *tc; int vntype; if (!de->d_inode) /* encode a negative dentry?! */ return 255; if (*max_len < 4) /* not enough space */ return 255; tvc = VTOAFS(de->d_inode); #ifdef OSI_EXPORT_DEBUG printk("afs: encode_fh(0x%08x/%d/%d.%d)\n", tvc->f.fid.Cell, tvc->f.fid.Fid.Volume, tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique); #endif if (afs_IsDynrootAnyFid(&tvc->f.fid)) { vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode); switch (vntype) { case 0: /* encode as a normal filehandle */ break; case VN_TYPE_MOUNT: if (*max_len < 5) { return 255; } /* fall through */ case VN_TYPE_CELL: case VN_TYPE_ALIAS: AFS_GLOCK(); tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode), READ_LOCK); if (!tc) { AFS_GUNLOCK(); return 255; } memcpy((void *)fh, tc->cellHandle, 16); afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); if (vntype == VN_TYPE_MOUNT) { fh[4] = htonl(tvc->f.fid.Fid.Unique); *max_len = 5; return AFSFH_DYN_MOUNT; } *max_len = 4; if (vntype == VN_TYPE_CELL) { return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode); } else { return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode); } case VN_TYPE_SYMLINK: /* XXX fill in filehandle for dynroot symlink */ /* XXX return AFSFH_DYN_SYMLINK; */ default: return 255; } } if (*max_len < 7) { /* not big enough for a migratable filehandle */ /* always encode in network order */ fh[0] = htonl(tvc->f.fid.Cell); fh[1] = htonl(tvc->f.fid.Fid.Volume); fh[2] = htonl(tvc->f.fid.Fid.Vnode); fh[3] = htonl(tvc->f.fid.Fid.Unique); *max_len = 4; return AFSFH_NET_VENUSFID; } AFS_GLOCK(); tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return 255; } memcpy((void *)fh, tc->cellHandle, 16); afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); /* always encode in network order */ fh[4] = htonl(tvc->f.fid.Fid.Volume); fh[5] = htonl(tvc->f.fid.Fid.Vnode); fh[6] = htonl(tvc->f.fid.Fid.Unique); *max_len = 7; return AFSFH_NET_CELLFID; }
int SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index, struct AFSDBLock *a_result) { struct ltable *tl; /*Ptr to lock table entry */ int nentries; /*Num entries in table */ int code; /*Return code */ XSTATS_DECLS; RX_AFS_GLOCK(); XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK); AFS_STATCNT(SRXAFSCB_GetLock); nentries = sizeof(ltable) / sizeof(struct ltable); if (a_index < 0 || a_index >= nentries+afs_cellindex) { /* * Past EOF */ code = 1; } else if (a_index >= nentries) { struct cell *tc = afs_GetCellByIndex(a_index-nentries, 0); strcpy(a_result->name, tc->cellName); a_result->lock.waitStates = ((struct afs_lock *)&(tc->lock))->wait_states; a_result->lock.exclLocked = ((struct afs_lock *)&(tc->lock))->excl_locked; a_result->lock.readersReading = ((struct afs_lock *)&(tc->lock))->readers_reading; a_result->lock.numWaiting = ((struct afs_lock *)&(tc->lock))->num_waiting; #ifdef INSTRUMENT_LOCKS a_result->lock.pid_last_reader = MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_last_reader); a_result->lock.pid_writer = MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_writer); a_result->lock.src_indicator = ((struct afs_lock *)&(tc->lock))->src_indicator; #else a_result->lock.pid_last_reader = 0; a_result->lock.pid_writer = 0; a_result->lock.src_indicator = 0; #endif code = 0; } else { /* * Found it - copy out its contents. */ tl = <able[a_index]; strcpy(a_result->name, tl->name); a_result->lock.waitStates = ((struct afs_lock *)(tl->addr))->wait_states; a_result->lock.exclLocked = ((struct afs_lock *)(tl->addr))->excl_locked; a_result->lock.readersReading = ((struct afs_lock *)(tl->addr))->readers_reading; a_result->lock.numWaiting = ((struct afs_lock *)(tl->addr))->num_waiting; #ifdef INSTRUMENT_LOCKS a_result->lock.pid_last_reader = MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_last_reader); a_result->lock.pid_writer = MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_writer); a_result->lock.src_indicator = ((struct afs_lock *)(tl->addr))->src_indicator; #else a_result->lock.pid_last_reader = 0; a_result->lock.pid_writer = 0; a_result->lock.src_indicator = 0; #endif code = 0; } XSTATS_END_TIME; RX_AFS_GUNLOCK(); return (code); } /*SRXAFSCB_GetLock */