/* * 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; }
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; }