static int UnEvalFakeStat(struct vrequest *areq, struct vcache **vcpp) { struct VenusFid tfid; struct volume *tvp; struct vcache *tvc; int code; if (!afs_fakestat_enable) return 0; if (*vcpp == afs_globalVp || vType(*vcpp) != VDIR || (*vcpp)->mvstat != 2) return 0; /* Figure out what FID to look for */ tvp = afs_GetVolume(&(*vcpp)->f.fid, 0, READ_LOCK); if (!tvp) { #ifdef OSI_EXPORT_DEBUG printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): no volume\n", (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume, (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique); #endif return ENOENT; } tfid = tvp->mtpoint; afs_PutVolume(tvp, READ_LOCK); tvc = afs_GetVCache(&tfid, areq, NULL, NULL); if (!tvc) { #ifdef OSI_EXPORT_DEBUG printk("afs: UnEvalFakeStat(0x%08x/%d/%d.%d): GetVCache(0x%08x/%d/%d.%d) failed\n", (*vcpp)->f.fid.Cell, (*vcpp)->f.fid.Fid.Volume, (*vcpp)->f.fid.Fid.Vnode, (*vcpp)->f.fid.Fid.Unique, tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique); #endif return ENOENT; } if (afs_fakestat_enable == 2) { ObtainWriteLock(&tvc->lock, 806); code = afs_HandleLink(tvc, areq); if (code) { ReleaseWriteLock(&tvc->lock); afs_PutVCache(tvc); return code; } if (!strchr(tvc->linkData, ':')) { ReleaseWriteLock(&tvc->lock); afs_PutVCache(tvc); return 0; } ReleaseWriteLock(&tvc->lock); } afs_PutVCache(*vcpp); *vcpp = tvc; return 0; }
int afs_readlink(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred) { afs_int32 code; struct vrequest *treq = NULL; char *tp; struct afs_fakestat_state fakestat; OSI_VC_CONVERT(avc); AFS_STATCNT(afs_readlink); afs_Trace1(afs_iclSetp, CM_TRACE_READLINK, ICL_TYPE_POINTER, avc); if ((code = afs_CreateReq(&treq, acred))) return code; afs_InitFakeStat(&fakestat); AFS_DISCON_LOCK(); code = afs_EvalFakeStat(&avc, &fakestat, treq); if (code) goto done; code = afs_VerifyVCache(avc, treq); if (code) goto done; if (vType(avc) != VLNK) { code = EINVAL; goto done; } ObtainWriteLock(&avc->lock, 158); code = afs_HandleLink(avc, treq); /* finally uiomove it to user-land */ if (code == 0) { tp = avc->linkData; if (tp) AFS_UIOMOVE(tp, strlen(tp), UIO_READ, auio, code); else { code = EIO; } } ReleaseWriteLock(&avc->lock); done: afs_PutFakeStat(&fakestat); AFS_DISCON_UNLOCK(); code = afs_CheckCode(code, treq, 32); afs_DestroyReq(treq); return code; }