struct vrequest treq;
struct vcache *vcp = ITOAFS(dp->d_inode);
struct vcache *rootvp = NULL;
+ struct afs_fakestat_state fakestat;
AFS_GLOCK();
- if (afs_fakestat_enable && vcp->mvstat == 1 && vcp->mvid &&
- (vcp->states & CMValid) && (vcp->states & CStatd)) {
- ObtainSharedLock(&afs_xvcache, 680);
- rootvp = afs_FindVCache(vcp->mvid, 0, 0);
- ReleaseSharedLock(&afs_xvcache);
+ afs_InitFakeStat(&fakestat);
+ if (vcp->mvstat == 1) {
+ afs_InitReq(&treq, credp);
+ rootvp = vcp;
+ code = afs_TryEvalFakeStat(&rootvp, &fakestat, &treq);
+ if (code) {
+ AFS_GUNLOCK();
+ return -code;
+ }
}
#ifdef AFS_LINUX24_ENV
if (vcp->states & CStatd) {
if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
check_bad_parent(dp); /* check and correct mvid */
- if (rootvp)
+ if (rootvp && rootvp != vcp)
vcache2fakeinode(rootvp, vcp);
else
vcache2inode(vcp);
#ifdef AFS_LINUX24_ENV
unlock_kernel();
#endif
- if (rootvp) afs_PutVCache(rootvp);
+ afs_PutFakeStat(&fakestat);
AFS_GUNLOCK();
return 0;
}
#ifdef AFS_LINUX24_ENV
unlock_kernel();
#endif
+ afs_PutFakeStat(&fakestat);
AFS_GUNLOCK();
crfree(credp);
*
* The actual implementation of afs_EvalFakeStat and afs_TryEvalFakeStat,
* which is called by those wrapper functions.
- *
- * Only issues RPCs if canblock is non-zero.
*/
-int afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state,
- struct vrequest *areq, int canblock)
+static int afs_EvalFakeStat_int(struct vcache **avcp,
+ struct afs_fakestat_state *state, struct vrequest *areq, int canblock)
{
struct vcache *tvc, *root_vp;
struct volume *tvolp = NULL;
if (tvc->mvstat != 1)
return 0;
- /* Is the call to VerifyVCache really necessary? */
code = afs_VerifyVCache(tvc, areq);
if (code)
goto done;
+
+ if (afs_fakestat_enable == 2 && !canblock) {
+ ObtainSharedLock(&tvc->lock, 680);
+ if (!tvc->linkData) {
+ UpgradeSToWLock(&tvc->lock, 681);
+ code = afs_HandleLink(tvc, areq);
+ if (code) {
+ ReleaseWriteLock(&tvc->lock);
+ goto done;
+ }
+ ConvertWToRLock(&tvc->lock);
+ } else {
+ ConvertSToRLock(&tvc->lock);
+ }
+
+ if (!afs_strchr(tvc->linkData, ':'))
+ canblock = 1;
+ ReleaseReadLock(&tvc->lock);
+ }
+
if (canblock) {
ObtainWriteLock(&tvc->lock, 599);
code = EvalMountPoint(tvc, NULL, &tvolp, areq);
extern char *afs_cv2string(char *ttp, afs_uint32 aval);
extern int afs_strcasecmp(char *s1, char *s2);
extern char *afs_strdup(char *s);
+extern char *afs_strchr(char *s, int c);
extern void print_internet_address(char *preamble, struct srvAddr *sa,
char *postamble, int flag);
extern afs_int32 afs_data_pointer_to_int32(const void *p);
return *s1 - *s2;
}
+char *afs_strchr(char *s, int c)
+{
+ char *p;
+
+ for (p = s; *p; p++)
+ if (*p == c)
+ return p;
+ return NULL;
+}
+
char *afs_strdup(char *s)
{
char *n;
}
if (as->parms[27].items) {
/* -fakestat */
+ enable_fakestat = 2;
+ }
+ if (as->parms[28].items) {
+ /* -fakestat-all */
enable_fakestat = 1;
}
if (enable_fakestat) {
if (afsd_verbose)
printf("%s: Enabling fakestat support in kernel.\n", rn);
- code = call_syscall(AFSOP_SET_FAKESTAT, 1);
+ code = call_syscall(AFSOP_SET_FAKESTAT, enable_fakestat);
if (code)
printf("%s: Error enabling fakestat support.\n", rn);
}
), "Enable AFSDB support");
cmd_AddParm(ts, "-files_per_subdir", CMD_SINGLE, CMD_OPTIONAL, "log(2) of the number of cache files per cache subdirectory");
cmd_AddParm(ts, "-dynroot", CMD_FLAG, CMD_OPTIONAL, "Enable dynroot support");
- cmd_AddParm(ts, "-fakestat", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support");
+ cmd_AddParm(ts, "-fakestat", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support for cross-cell mounts");
+ cmd_AddParm(ts, "-fakestat-all", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support for all mounts");
return (cmd_Dispatch(argc, argv));
}