mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 06:50:12 +00:00
Initial fakestat support (fake mountpoint directory attributes).
Useful for quickly stat'ing everything under /afs, for instance. Reasonably tested on Solaris, and appears to work on Linux too. Enable with 'afsd -fakestat'.
This commit is contained in:
parent
fd318a1fc9
commit
6b33ed2b05
7
NEWS
7
NEWS
@ -1,5 +1,12 @@
|
||||
OpenAFS News -- history of user-visible changes. October 19, 2001
|
||||
|
||||
* Changes incorporated in OpenAFS 1.3
|
||||
|
||||
** Mountpoint directory information can be faked by the cache manager,
|
||||
making operations such as stat'ing all cells under /afs much faster.
|
||||
This is enabled by passing -fakestat to afsd, but might not be stable
|
||||
on all platforms.
|
||||
|
||||
* Changes incorporated in OpenAFS 1.2.3
|
||||
|
||||
** Cell aliases for dynroot can be specified in the CellAlias file in
|
||||
|
@ -261,6 +261,7 @@ static int afs_linux_readdir(struct file *fp,
|
||||
int len;
|
||||
afs_size_t origOffset, tlen;
|
||||
cred_t *credp = crref();
|
||||
struct afs_fakestat_state fakestat;
|
||||
|
||||
AFS_GLOCK();
|
||||
AFS_STATCNT(afs_readdir);
|
||||
@ -272,10 +273,19 @@ static int afs_linux_readdir(struct file *fp,
|
||||
return -code;
|
||||
}
|
||||
|
||||
afs_InitFakeStat(&fakestat);
|
||||
code = afs_EvalFakeStat(&avc, &fakestat, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
AFS_GUNLOCK();
|
||||
return -code;
|
||||
}
|
||||
|
||||
/* update the cache entry */
|
||||
tagain:
|
||||
code = afs_VerifyVCache(avc, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
AFS_GUNLOCK();
|
||||
return -code;
|
||||
}
|
||||
@ -284,6 +294,7 @@ tagain:
|
||||
tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
|
||||
len = tlen;
|
||||
if (!tdc) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
AFS_GUNLOCK();
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -380,6 +391,7 @@ tagain:
|
||||
ReleaseReadLock(&tdc->lock);
|
||||
afs_PutDCache(tdc);
|
||||
ReleaseReadLock(&avc->lock);
|
||||
afs_PutFakeStat(&fakestat);
|
||||
AFS_GUNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
@ -188,22 +188,32 @@ afs_access(OSI_VC_ARG(avc), amode, acred)
|
||||
struct AFS_UCRED *acred; {
|
||||
register afs_int32 code;
|
||||
struct vrequest treq;
|
||||
struct afs_fakestat_state fakestate;
|
||||
OSI_VC_CONVERT(avc)
|
||||
|
||||
AFS_STATCNT(afs_access);
|
||||
afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
|
||||
ICL_TYPE_INT32, amode,
|
||||
ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
|
||||
afs_InitFakeStat(&fakestate);
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
|
||||
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
|
||||
code = afs_VerifyVCache(avc, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 16);
|
||||
return code;
|
||||
}
|
||||
|
||||
/* if we're looking for write access and we have a read-only file system, report it */
|
||||
if ((amode & VWRITE) && (avc->states & CRO)) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return EROFS;
|
||||
}
|
||||
code = 1; /* Default from here on in is access ok. */
|
||||
@ -270,11 +280,12 @@ afs_access(OSI_VC_ARG(avc), amode, acred)
|
||||
code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
|
||||
}
|
||||
}
|
||||
if (code)
|
||||
afs_PutFakeStat(&fakestate);
|
||||
if (code) {
|
||||
return 0; /* if access is ok */
|
||||
else {
|
||||
code = afs_CheckCode(EACCES, &treq, 17); /* failure code */
|
||||
return code;
|
||||
} else {
|
||||
code = afs_CheckCode(EACCES, &treq, 17); /* failure code */
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,20 +37,24 @@ extern struct vcache *afs_globalVp;
|
||||
/* copy out attributes from cache entry */
|
||||
afs_CopyOutAttrs(avc, attrs)
|
||||
register struct vattr *attrs;
|
||||
register struct vcache *avc; {
|
||||
register struct vcache *avc;
|
||||
{
|
||||
register struct volume *tvp;
|
||||
register struct cell *tcell;
|
||||
register afs_int32 i;
|
||||
int fakedir = 0;
|
||||
|
||||
AFS_STATCNT(afs_CopyOutAttrs);
|
||||
if (afs_fakestat_enable && avc->mvstat == 1)
|
||||
fakedir = 1;
|
||||
#if defined(AFS_MACH_ENV )
|
||||
attrs->va_mode = vType(avc) | (avc->m.Mode&~VFMT);
|
||||
attrs->va_mode = fakedir ? VDIR | 0755 : vType(avc) | (avc->m.Mode&~VFMT);
|
||||
#else /* AFS_MACH_ENV */
|
||||
attrs->va_type = vType(avc);
|
||||
attrs->va_type = fakedir ? VDIR : vType(avc);
|
||||
#if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
|
||||
attrs->va_mode = (mode_t)(avc->m.Mode & 0xffff);
|
||||
attrs->va_mode = fakedir ? 0755 : (mode_t)(avc->m.Mode & 0xffff);
|
||||
#else
|
||||
attrs->va_mode = avc->m.Mode;
|
||||
attrs->va_mode = fakedir ? VDIR | 0755 : avc->m.Mode;
|
||||
#endif
|
||||
#endif /* AFS_MACH_ENV */
|
||||
|
||||
@ -60,8 +64,8 @@ afs_CopyOutAttrs(avc, attrs)
|
||||
if (tcell && (tcell->states & CNoSUID))
|
||||
attrs->va_mode &= ~(VSUID|VSGID);
|
||||
}
|
||||
attrs->va_uid = avc->m.Owner;
|
||||
attrs->va_gid = avc->m.Group; /* yeah! */
|
||||
attrs->va_uid = fakedir ? 0 : avc->m.Owner;
|
||||
attrs->va_gid = fakedir ? 0 : avc->m.Group; /* yeah! */
|
||||
#if defined(AFS_SUN56_ENV)
|
||||
attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
|
||||
#else
|
||||
@ -90,10 +94,10 @@ afs_CopyOutAttrs(avc, attrs)
|
||||
}
|
||||
else attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
|
||||
attrs->va_nodeid &= 0x7fffffff; /* Saber C hates negative inode #s! */
|
||||
attrs->va_nlink = avc->m.LinkCount;
|
||||
attrs->va_size = avc->m.Length;
|
||||
attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
|
||||
attrs->va_size = fakedir ? 4096 : avc->m.Length;
|
||||
attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
|
||||
avc->m.Date;
|
||||
fakedir ? 0 : avc->m.Date;
|
||||
/* set microseconds to be dataversion # so that we approximate NFS-style
|
||||
* use of mtime as a dataversion #. We take it mod 512K because
|
||||
* microseconds *must* be less than a million, and 512K is the biggest
|
||||
@ -203,6 +207,23 @@ afs_getattr(OSI_VC_ARG(avc), attrs, acred)
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_GETATTR, ICL_TYPE_POINTER, avc,
|
||||
ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
|
||||
|
||||
if (afs_fakestat_enable && avc->mvstat == 1) {
|
||||
struct afs_fakestat_state fakestat;
|
||||
|
||||
code = afs_InitReq(&treq, acred);
|
||||
if (code) return code;
|
||||
afs_InitFakeStat(&fakestat);
|
||||
code = afs_TryEvalFakeStat(&avc, &fakestat, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return code;
|
||||
}
|
||||
|
||||
code = afs_CopyOutAttrs(avc, attrs);
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return code;
|
||||
}
|
||||
|
||||
#if defined(AFS_SUN5_ENV)
|
||||
if (flags & ATTR_HINT) {
|
||||
code = afs_CopyOutAttrs(avc, attrs);
|
||||
@ -403,12 +424,19 @@ afs_setattr(avc, attrs, acred)
|
||||
struct vrequest treq;
|
||||
struct AFSStoreStatus astat;
|
||||
register afs_int32 code;
|
||||
struct afs_fakestat_state fakestate;
|
||||
OSI_VC_CONVERT(avc)
|
||||
|
||||
AFS_STATCNT(afs_setattr);
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_SETATTR, ICL_TYPE_POINTER, avc,
|
||||
ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
|
||||
if (code)
|
||||
goto done;
|
||||
|
||||
if (avc->states & CRO) {
|
||||
code=EROFS;
|
||||
goto done;
|
||||
@ -528,6 +556,7 @@ afs_setattr(avc, attrs, acred)
|
||||
AFS_RWUNLOCK((vnode_t *)avc, VRWLOCK_WRITE);
|
||||
#endif
|
||||
done:
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 15);
|
||||
return code;
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ afs_create(OSI_VC_ARG(adp), aname, attrs, aexcl, amode, avcp, acred)
|
||||
struct server *hostp=0;
|
||||
struct vcache *tvc;
|
||||
struct volume* volp = 0;
|
||||
struct afs_fakestat_state fakestate;
|
||||
XSTATS_DECLS
|
||||
OSI_VC_CONVERT(adp)
|
||||
|
||||
@ -83,6 +84,8 @@ afs_create(OSI_VC_ARG(adp), aname, attrs, aexcl, amode, avcp, acred)
|
||||
afs_Trace3(afs_iclSetp, CM_TRACE_CREATE, ICL_TYPE_POINTER, adp,
|
||||
ICL_TYPE_STRING, aname, ICL_TYPE_INT32, amode);
|
||||
|
||||
afs_InitFakeStat(&fakestate);
|
||||
|
||||
#ifdef AFS_SGI65_ENV
|
||||
/* If avcp is passed not null, it's the old reference to this file.
|
||||
* We can use this to avoid create races. For now, just decrement
|
||||
@ -112,6 +115,8 @@ afs_create(OSI_VC_ARG(adp), aname, attrs, aexcl, amode, avcp, acred)
|
||||
code = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
|
||||
if (code) goto done;
|
||||
tagain:
|
||||
code = afs_VerifyVCache(adp, &treq);
|
||||
if (code) goto done;
|
||||
@ -469,6 +474,7 @@ done:
|
||||
tvc->states |= CCore1;
|
||||
#endif
|
||||
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 20);
|
||||
|
||||
done2:
|
||||
|
@ -62,6 +62,7 @@ afs_mkdir(OSI_VC_ARG(adp), aname, attrs, avcp, acred)
|
||||
struct AFSCallBack CallBack;
|
||||
struct AFSVolSync tsync;
|
||||
afs_int32 now;
|
||||
struct afs_fakestat_state fakestate;
|
||||
XSTATS_DECLS
|
||||
OSI_VC_CONVERT(adp)
|
||||
|
||||
@ -71,6 +72,7 @@ afs_mkdir(OSI_VC_ARG(adp), aname, attrs, avcp, acred)
|
||||
|
||||
if (code = afs_InitReq(&treq, acred))
|
||||
goto done2;
|
||||
afs_InitFakeStat(&fakestate);
|
||||
|
||||
if (strlen(aname) > AFSNAMEMAX) {
|
||||
code = ENAMETOOLONG;
|
||||
@ -81,6 +83,8 @@ afs_mkdir(OSI_VC_ARG(adp), aname, attrs, avcp, acred)
|
||||
code = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
|
||||
if (code) goto done;
|
||||
code = afs_VerifyVCache(adp, &treq);
|
||||
if (code) goto done;
|
||||
|
||||
@ -159,6 +163,7 @@ afs_mkdir(OSI_VC_ARG(adp), aname, attrs, avcp, acred)
|
||||
}
|
||||
else code = ENOENT;
|
||||
done:
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 26);
|
||||
done2:
|
||||
#ifdef AFS_OSF_ENV
|
||||
@ -194,6 +199,7 @@ afs_rmdir(adp, aname, acred)
|
||||
afs_size_t offset, len;
|
||||
struct AFSFetchStatus OutDirStatus;
|
||||
struct AFSVolSync tsync;
|
||||
struct afs_fakestat_state fakestate;
|
||||
XSTATS_DECLS
|
||||
OSI_VC_CONVERT(adp)
|
||||
|
||||
@ -202,14 +208,19 @@ afs_rmdir(adp, aname, acred)
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_RMDIR, ICL_TYPE_POINTER, adp,
|
||||
ICL_TYPE_STRING, aname);
|
||||
|
||||
if (code = afs_InitReq(&treq, acred))
|
||||
if (code = afs_InitReq(&treq, acred))
|
||||
goto done2;
|
||||
afs_InitFakeStat(&fakestate);
|
||||
|
||||
if (strlen(aname) > AFSNAMEMAX) {
|
||||
code = ENAMETOOLONG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
|
||||
if (code)
|
||||
goto done;
|
||||
|
||||
code = afs_VerifyVCache(adp, &treq);
|
||||
if (code) goto done;
|
||||
|
||||
@ -314,6 +325,7 @@ afs_rmdir(adp, aname, acred)
|
||||
code = 0;
|
||||
|
||||
done:
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 27);
|
||||
done2:
|
||||
#ifdef AFS_OSF_ENV
|
||||
|
@ -503,11 +503,21 @@ struct AFS_UCRED *acred; {
|
||||
#ifdef AFS_OSF_ENV
|
||||
int acmd = 0;
|
||||
#endif
|
||||
struct afs_fakestat_state fakestate;
|
||||
|
||||
AFS_STATCNT(afs_lockctl);
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&fakestate, &avc, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
#ifdef AFS_OSF_ENV
|
||||
if (flag & VNOFLCK) return 0;
|
||||
if (flag & VNOFLCK) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return 0;
|
||||
}
|
||||
if (flag & CLNFLCK) {
|
||||
acmd = LOCK_UN;
|
||||
} else if ((flag & GETFLCK) || (flag & RGETFLCK)) {
|
||||
@ -521,12 +531,15 @@ struct AFS_UCRED *acred; {
|
||||
#else
|
||||
if (acmd == F_GETLK) {
|
||||
#endif
|
||||
if (af->l_type == F_UNLCK)
|
||||
if (af->l_type == F_UNLCK) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return 0;
|
||||
}
|
||||
#ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
|
||||
code = HandleGetLock(avc, af, &treq, clid);
|
||||
#endif
|
||||
code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
|
||||
@ -554,13 +567,17 @@ struct AFS_UCRED *acred; {
|
||||
even when they should block */
|
||||
if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
|
||||
DoLockWarning();
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return 0;
|
||||
}
|
||||
/* otherwise we can turn this into a whole-file flock */
|
||||
if (af->l_type == F_RDLCK) code = LOCK_SH;
|
||||
else if (af->l_type == F_WRLCK) code = LOCK_EX;
|
||||
else if (af->l_type == F_UNLCK) code = LOCK_UN;
|
||||
else return EINVAL; /* unknown lock type */
|
||||
else {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return EINVAL; /* unknown lock type */
|
||||
}
|
||||
if (((acmd == F_SETLK)
|
||||
#if (defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV)) && !defined(AFS_SUN58_ENV)
|
||||
|| (acmd == F_RSETLK)
|
||||
@ -579,8 +596,10 @@ struct AFS_UCRED *acred; {
|
||||
#endif
|
||||
#endif
|
||||
code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
@ -859,7 +878,9 @@ afs_xflock () {
|
||||
struct vrequest treq;
|
||||
struct vcache *tvc;
|
||||
int flockDone;
|
||||
struct afs_fakestat_state fakestate;
|
||||
|
||||
afs_InitFakeStat(&fakestate);
|
||||
AFS_STATCNT(afs_xflock);
|
||||
flockDone = 0;
|
||||
#ifdef AFS_OSF_ENV
|
||||
@ -869,9 +890,15 @@ afs_xflock () {
|
||||
uap = (struct a *)u.u_ap;
|
||||
fd = getf(uap->fd);
|
||||
#endif
|
||||
if (!fd) return;
|
||||
if (!fd) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flockDone = afs_InitReq(&treq, u.u_cred)) return flockDone;
|
||||
if (flockDone = afs_InitReq(&treq, u.u_cred)) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return flockDone;
|
||||
}
|
||||
/* first determine whether this is any sort of vnode */
|
||||
if (fd->f_type == DTYPE_VNODE) {
|
||||
/* good, this is a vnode; next see if it is an AFS vnode */
|
||||
@ -885,9 +912,15 @@ afs_xflock () {
|
||||
tvc = VTOAFS(afs_gntovn)(tvc);
|
||||
if (!tvc) {
|
||||
u.u_error = ENOENT;
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
code = afs_EvalFakeStat(&fakestate, &tvc, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
if ((fd->f_flag & (FEXLOCK | FSHLOCK)) && !(uap->com & LOCK_UN)) {
|
||||
/* First, if fd already has lock, release it for relock path */
|
||||
#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV))
|
||||
@ -935,6 +968,7 @@ afs_xflock () {
|
||||
#else
|
||||
FP_UNREF(fd);
|
||||
#endif
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
#else /* AFS_OSF_ENV */
|
||||
if (!flockDone)
|
||||
@ -943,6 +977,7 @@ afs_xflock () {
|
||||
#else
|
||||
flock();
|
||||
#endif
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ extern struct inode_operations afs_symlink_iops, afs_dir_iops;
|
||||
|
||||
afs_int32 afs_bulkStatsDone;
|
||||
static int bulkStatCounter = 0; /* counter for bulk stat seq. numbers */
|
||||
int afs_fakestat_enable = 0;
|
||||
|
||||
|
||||
/* this would be faster if it did comparison as int32word, but would be
|
||||
@ -90,8 +91,9 @@ char *afs_index(a, c)
|
||||
}
|
||||
|
||||
/* call under write lock, evaluate mvid field from a mt pt.
|
||||
* avc is the vnode of the mount point object.
|
||||
* advc is the vnode of the containing directory
|
||||
* avc is the vnode of the mount point object; must be write-locked.
|
||||
* advc is the vnode of the containing directory (optional; if NULL and
|
||||
* EvalMountPoint succeeds, caller must initialize *avolpp->dotdot)
|
||||
* avolpp is where we return a pointer to the volume named by the mount pt, if success
|
||||
* areq is the identity of the caller.
|
||||
*
|
||||
@ -231,11 +233,159 @@ EvalMountPoint(avc, advc, avolpp, areq)
|
||||
* to the new path.
|
||||
*/
|
||||
tvp->mtpoint = avc->fid; /* setup back pointer to mtpoint */
|
||||
tvp->dotdot = advc->fid;
|
||||
if (advc) tvp->dotdot = advc->fid;
|
||||
|
||||
*avolpp = tvp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* afs_InitFakeStat
|
||||
*
|
||||
* Must be called on an afs_fakestat_state object before calling
|
||||
* afs_EvalFakeStat or afs_PutFakeStat. Calling afS_PutFakeStat
|
||||
* without calling afs_EvalFakeStat is legal, as long as this
|
||||
* function is called.
|
||||
*/
|
||||
|
||||
void
|
||||
afs_InitFakeStat(state)
|
||||
struct afs_fakestat_state *state;
|
||||
{
|
||||
state->valid = 1;
|
||||
state->did_eval = 0;
|
||||
state->need_release = 0;
|
||||
state->nonblock = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* afs_EvalFakeStat
|
||||
*
|
||||
* Automatically does the equivalent of EvalMountPoint for vcache entries
|
||||
* which are mount points. Remembers enough state to properly release
|
||||
* the volume root vcache when afs_PutFakeStat() is called.
|
||||
*
|
||||
* State variable must be initialized by afs_InitFakeState() beforehand.
|
||||
*
|
||||
* Returns 0 when everything succeeds and *avcp points to the vcache entry
|
||||
* that should be used for the real vnode operation. Returns non-zero if
|
||||
* something goes wrong and the error code should be returned to the user.
|
||||
*/
|
||||
int
|
||||
afs_EvalFakeStat(avcp, state, areq)
|
||||
struct vcache **avcp;
|
||||
struct afs_fakestat_state *state;
|
||||
struct vrequest *areq;
|
||||
{
|
||||
struct vcache *tvc, *root_vp;
|
||||
struct volume *tvolp = NULL;
|
||||
int code = 0;
|
||||
|
||||
osi_Assert(state->valid == 1);
|
||||
osi_Assert(state->did_eval == 0);
|
||||
state->did_eval = 1;
|
||||
if (!afs_fakestat_enable)
|
||||
return 0;
|
||||
tvc = *avcp;
|
||||
if (tvc->mvstat != 1)
|
||||
return 0;
|
||||
|
||||
/* Is the call to VerifyVCache really necessary? */
|
||||
code = afs_VerifyVCache(tvc, areq);
|
||||
if (code)
|
||||
goto done;
|
||||
if (!state->nonblock) {
|
||||
ObtainWriteLock(&tvc->lock, 599);
|
||||
code = EvalMountPoint(tvc, NULL, &tvolp, areq);
|
||||
ReleaseWriteLock(&tvc->lock);
|
||||
if (code)
|
||||
goto done;
|
||||
if (tvolp) {
|
||||
tvolp->dotdot = tvc->fid;
|
||||
tvolp->dotdot.Fid.Vnode = tvc->parentVnode;
|
||||
tvolp->dotdot.Fid.Unique = tvc->parentUnique;
|
||||
}
|
||||
}
|
||||
if (tvc->mvid && (tvc->states & CMValid)) {
|
||||
if (state->nonblock) {
|
||||
afs_int32 retry;
|
||||
|
||||
do {
|
||||
retry = 0;
|
||||
ObtainWriteLock(&afs_xvcache, 597);
|
||||
root_vp = afs_FindVCache(tvc->mvid, 0, 0, &retry, 0);
|
||||
if (root_vp && retry) {
|
||||
ReleaseWriteLock(&afs_xvcache);
|
||||
afs_PutVCache(root_vp, 0);
|
||||
}
|
||||
} while (root_vp && retry);
|
||||
ReleaseWriteLock(&afs_xvcache);
|
||||
} else {
|
||||
root_vp = afs_GetVCache(tvc->mvid, areq, NULL, NULL, WRITE_LOCK);
|
||||
}
|
||||
if (!root_vp) {
|
||||
code = state->nonblock ? 0 : ENOENT;
|
||||
goto done;
|
||||
}
|
||||
if (tvolp) {
|
||||
/* Is this always kosher? Perhaps we should instead use
|
||||
* NBObtainWriteLock to avoid potential deadlock.
|
||||
*/
|
||||
ObtainWriteLock(&root_vp->lock, 598);
|
||||
if (!root_vp->mvid)
|
||||
root_vp->mvid = osi_AllocSmallSpace(sizeof(struct VenusFid));
|
||||
*root_vp->mvid = tvolp->dotdot;
|
||||
ReleaseWriteLock(&root_vp->lock);
|
||||
}
|
||||
state->need_release = 1;
|
||||
state->root_vp = root_vp;
|
||||
*avcp = root_vp;
|
||||
code = 0;
|
||||
} else {
|
||||
code = state->nonblock ? 0 : ENOENT;
|
||||
}
|
||||
|
||||
done:
|
||||
if (tvolp)
|
||||
afs_PutVolume(tvolp, WRITE_LOCK);
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
* afs_TryEvalFakeStat
|
||||
*
|
||||
* Same as afs_EvalFakeStat, but tries not to talk to remote servers
|
||||
* and only evaluate the mount point if all the data is already in
|
||||
* local caches.
|
||||
*
|
||||
* Returns 0 if everything succeeds and *avcp points to a valid
|
||||
* vcache entry (possibly evaluated).
|
||||
*/
|
||||
int
|
||||
afs_TryEvalFakeStat(avcp, state, areq)
|
||||
struct vcache **avcp;
|
||||
struct afs_fakestat_state *state;
|
||||
struct vrequest *areq;
|
||||
{
|
||||
state->nonblock = 1;
|
||||
return afs_EvalFakeStat(avcp, state, areq);
|
||||
}
|
||||
|
||||
/*
|
||||
* afs_PutFakeStat
|
||||
*
|
||||
* Perform any necessary cleanup at the end of a vnode op, given that
|
||||
* afs_InitFakeStat was previously called with this state.
|
||||
*/
|
||||
void
|
||||
afs_PutFakeStat(state)
|
||||
struct afs_fakestat_state *state;
|
||||
{
|
||||
osi_Assert(state->valid == 1);
|
||||
if (state->need_release)
|
||||
afs_PutVCache(state->root_vp, 0);
|
||||
state->valid = 0;
|
||||
}
|
||||
|
||||
afs_ENameOK(aname)
|
||||
register char *aname; {
|
||||
@ -932,8 +1082,17 @@ afs_lookup(adp, aname, avcp, acred)
|
||||
int no_read_access = 0;
|
||||
struct sysname_info sysState; /* used only for @sys checking */
|
||||
int dynrootRetry = 1;
|
||||
struct afs_fakestat_state fakestate;
|
||||
|
||||
AFS_STATCNT(afs_lookup);
|
||||
afs_InitFakeStat(&fakestate);
|
||||
|
||||
if (code = afs_InitReq(&treq, acred))
|
||||
goto done;
|
||||
|
||||
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
|
||||
if (code)
|
||||
goto done;
|
||||
#ifdef AFS_OSF_ENV
|
||||
ndp->ni_dvp = AFSTOV(adp);
|
||||
memcpy(aname, ndp->ni_ptr, ndp->ni_namelen);
|
||||
@ -942,10 +1101,6 @@ afs_lookup(adp, aname, avcp, acred)
|
||||
|
||||
*avcp = (struct vcache *) 0; /* Since some callers don't initialize it */
|
||||
|
||||
if (code = afs_InitReq(&treq, acred)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* come back to here if we encounter a non-existent object in a read-only
|
||||
volume's directory */
|
||||
|
||||
@ -1232,9 +1387,9 @@ afs_lookup(adp, aname, avcp, acred)
|
||||
if (!(flags & AFS_LOOKUP_NOEVAL))
|
||||
/* don't eval mount points */
|
||||
#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
|
||||
if (tvc->mvstat == 1) {
|
||||
/* a mt point, possibly unevaluated */
|
||||
struct volume *tvolp;
|
||||
if (!afs_fakestat_enable && tvc->mvstat == 1) {
|
||||
/* a mt point, possibly unevaluated */
|
||||
struct volume *tvolp;
|
||||
|
||||
ObtainWriteLock(&tvc->lock,133);
|
||||
code = EvalMountPoint(tvc, adp, &tvolp, &treq);
|
||||
@ -1334,6 +1489,7 @@ done:
|
||||
if (!FidCmp(&(tvc->fid), &(adp->fid))) {
|
||||
afs_PutVCache(*avcp, WRITE_LOCK);
|
||||
*avcp = NULL;
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return afs_CheckCode(EISDIR, &treq, 18);
|
||||
}
|
||||
}
|
||||
@ -1357,6 +1513,7 @@ done:
|
||||
/* So Linux inode cache is up to date. */
|
||||
code = afs_VerifyVCache(tvc, &treq);
|
||||
#else
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return 0; /* can't have been any errors if hit and !code */
|
||||
#endif
|
||||
}
|
||||
@ -1370,5 +1527,6 @@ done:
|
||||
*avcp = (struct vcache *)0;
|
||||
}
|
||||
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
|
@ -44,8 +44,9 @@ afs_open(avcp, aflags, acred)
|
||||
{
|
||||
register afs_int32 code;
|
||||
struct vrequest treq;
|
||||
register struct vcache *tvc;
|
||||
struct vcache *tvc;
|
||||
int writing;
|
||||
struct afs_fakestat_state fakestate;
|
||||
|
||||
AFS_STATCNT(afs_open);
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
@ -57,6 +58,9 @@ afs_open(avcp, aflags, acred)
|
||||
#endif
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
|
||||
ICL_TYPE_INT32, aflags);
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
|
||||
if (code) goto done;
|
||||
code = afs_VerifyVCache(tvc, &treq);
|
||||
if (code) goto done;
|
||||
if (aflags & (FWRITE | FTRUNC)) writing = 1;
|
||||
@ -143,6 +147,7 @@ afs_open(avcp, aflags, acred)
|
||||
#endif
|
||||
ReleaseReadLock(&tvc->lock);
|
||||
done:
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 4); /* avoid AIX -O bug */
|
||||
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
|
||||
|
@ -483,6 +483,7 @@ afs_readdir(OSI_VC_ARG(avc), auio, acred)
|
||||
struct DirEntry *ode = 0, *nde = 0;
|
||||
int o_slen = 0, n_slen = 0;
|
||||
afs_uint32 us;
|
||||
struct afs_fakestat_state fakestate;
|
||||
#if defined(AFS_SGI53_ENV)
|
||||
afs_int32 use64BitDirent;
|
||||
#endif /* defined(AFS_SGI53_ENV) */
|
||||
@ -535,6 +536,9 @@ afs_readdir(OSI_VC_ARG(avc), auio, acred)
|
||||
return code;
|
||||
}
|
||||
/* update the cache entry */
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
|
||||
if (code) goto done;
|
||||
tagain:
|
||||
code = afs_VerifyVCache(avc, &treq);
|
||||
if (code) goto done;
|
||||
@ -779,6 +783,7 @@ done:
|
||||
#ifdef AFS_HPUX_ENV
|
||||
osi_FreeSmallSpace((char *)sdirEntry);
|
||||
#endif
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 28);
|
||||
return code;
|
||||
}
|
||||
@ -809,6 +814,7 @@ afs1_readdir(avc, auio, acred)
|
||||
struct minnfs_direct *sdirEntry = (struct minnfs_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
|
||||
afs_int32 rlen;
|
||||
#endif
|
||||
struct afs_fakestat_state fakestate;
|
||||
|
||||
AFS_STATCNT(afs_readdir);
|
||||
#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
|
||||
@ -820,6 +826,15 @@ afs1_readdir(avc, auio, acred)
|
||||
#endif
|
||||
return code;
|
||||
}
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&fakestate, &avc, &treq);
|
||||
if (code) {
|
||||
#ifdef AFS_HPUX_ENV
|
||||
osi_FreeSmallSpace((char *)sdirEntry);
|
||||
#endif
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
/* update the cache entry */
|
||||
tagain:
|
||||
code = afs_VerifyVCache(avc, &treq);
|
||||
@ -1014,6 +1029,7 @@ done:
|
||||
#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
|
||||
osi_FreeSmallSpace((char *)sdirEntry);
|
||||
#endif
|
||||
afs_PutFakeStat(&fakestate);
|
||||
code = afs_CheckCode(code, &treq, 29);
|
||||
return code;
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ afs_remove(OSI_VC_ARG(adp), aname, acred)
|
||||
afs_size_t offset, len;
|
||||
struct AFSFetchStatus OutDirStatus;
|
||||
struct AFSVolSync tsync;
|
||||
struct afs_fakestat_state fakestate;
|
||||
XSTATS_DECLS
|
||||
OSI_VC_CONVERT(adp)
|
||||
|
||||
@ -241,23 +242,37 @@ afs_remove(OSI_VC_ARG(adp), aname, acred)
|
||||
tvc = (struct vcache *)ndp->ni_vp; /* should never be null */
|
||||
#endif
|
||||
|
||||
/* Check if this is dynroot */
|
||||
if (afs_IsDynroot(adp)) {
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
#endif
|
||||
return afs_DynrootVOPRemove(adp, acred, aname);
|
||||
}
|
||||
|
||||
if (code = afs_InitReq(&treq, acred)) {
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
#endif
|
||||
return code;
|
||||
return code;
|
||||
}
|
||||
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
#endif
|
||||
return code;
|
||||
}
|
||||
|
||||
/* Check if this is dynroot */
|
||||
if (afs_IsDynroot(adp)) {
|
||||
code = afs_DynrootVOPRemove(adp, acred, aname);
|
||||
afs_PutFakeStat(&fakestate);
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
#endif
|
||||
return code;
|
||||
}
|
||||
if (strlen(aname) > AFSNAMEMAX) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
@ -271,13 +286,15 @@ tagain:
|
||||
if (code) {
|
||||
afs_PutVCache(adp, 0);
|
||||
afs_PutVCache(tvc, 0);
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return afs_CheckCode(code, &treq, 22);
|
||||
}
|
||||
#else /* AFS_OSF_ENV */
|
||||
tvc = (struct vcache *) 0;
|
||||
if (code) {
|
||||
code = afs_CheckCode(code, &treq, 23);
|
||||
return code;
|
||||
code = afs_CheckCode(code, &treq, 23);
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -290,6 +307,7 @@ tagain:
|
||||
afs_PutVCache(tvc, 0);
|
||||
#endif
|
||||
code = EROFS;
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -386,6 +404,7 @@ tagain:
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_PutVCache(adp, WRITE_LOCK);
|
||||
#endif /* AFS_OSF_ENV */
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,12 @@ extern afs_rwlock_t afs_xcbhash;
|
||||
/* Note that we don't set CDirty here, this is OK because the rename
|
||||
* RPC is called synchronously. */
|
||||
|
||||
afsrename(aodp, aname1, andp, aname2, acred)
|
||||
register struct vcache *aodp, *andp;
|
||||
afsrename(aodp, aname1, andp, aname2, acred, areq)
|
||||
struct vcache *aodp, *andp;
|
||||
char *aname1, *aname2;
|
||||
struct AFS_UCRED *acred; {
|
||||
struct vrequest treq;
|
||||
struct AFS_UCRED *acred;
|
||||
struct vrequest *areq;
|
||||
{
|
||||
register struct conn *tc;
|
||||
register afs_int32 code;
|
||||
afs_int32 returnCode;
|
||||
@ -53,8 +54,6 @@ afsrename(aodp, aname1, andp, aname2, acred)
|
||||
ICL_TYPE_STRING, aname1, ICL_TYPE_POINTER, andp,
|
||||
ICL_TYPE_STRING, aname2);
|
||||
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
|
||||
if (strlen(aname1) > AFSNAMEMAX || strlen(aname2) > AFSNAMEMAX) {
|
||||
code = ENAMETOOLONG;
|
||||
goto done;
|
||||
@ -62,9 +61,9 @@ afsrename(aodp, aname1, andp, aname2, acred)
|
||||
|
||||
/* verify the latest versions of the stat cache entries */
|
||||
tagain:
|
||||
code = afs_VerifyVCache(aodp, &treq);
|
||||
code = afs_VerifyVCache(aodp, areq);
|
||||
if (code) goto done;
|
||||
code = afs_VerifyVCache(andp, &treq);
|
||||
code = afs_VerifyVCache(andp, areq);
|
||||
if (code) goto done;
|
||||
|
||||
/* lock in appropriate order, after some checks */
|
||||
@ -83,7 +82,7 @@ tagain:
|
||||
goto done;
|
||||
}
|
||||
ObtainWriteLock(&andp->lock,147);
|
||||
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, &treq, &offset, &len, 0);
|
||||
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
|
||||
if (!tdc1) {
|
||||
code = ENOENT;
|
||||
} else {
|
||||
@ -101,7 +100,7 @@ tagain:
|
||||
ObtainWriteLock(&aodp->lock,149);
|
||||
tdc2 = afs_FindDCache(andp, 0);
|
||||
if (tdc2) ObtainWriteLock(&tdc2->lock, 644);
|
||||
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, &treq, &offset, &len, 0);
|
||||
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
|
||||
if (tdc1)
|
||||
ObtainWriteLock(&tdc1->lock, 645);
|
||||
else
|
||||
@ -110,7 +109,7 @@ tagain:
|
||||
else {
|
||||
ObtainWriteLock(&aodp->lock,150); /* lock smaller one first */
|
||||
ObtainWriteLock(&andp->lock,557);
|
||||
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, &treq, &offset, &len, 0);
|
||||
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
|
||||
if (tdc1)
|
||||
ObtainWriteLock(&tdc1->lock, 646);
|
||||
else
|
||||
@ -166,7 +165,7 @@ tagain:
|
||||
|
||||
/* locks are now set, proceed to do the real work */
|
||||
do {
|
||||
tc = afs_Conn(&aodp->fid, &treq, SHARED_LOCK);
|
||||
tc = afs_Conn(&aodp->fid, areq, SHARED_LOCK);
|
||||
if (tc) {
|
||||
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
|
||||
#ifdef RX_ENABLE_LOCKS
|
||||
@ -182,7 +181,7 @@ tagain:
|
||||
} else code = -1;
|
||||
|
||||
} while
|
||||
(afs_Analyze(tc, code, &andp->fid, &treq,
|
||||
(afs_Analyze(tc, code, &andp->fid, areq,
|
||||
AFS_STATS_FS_RPCIDX_RENAME, SHARED_LOCK, (struct cell *)0));
|
||||
|
||||
returnCode = code; /* remember for later */
|
||||
@ -296,11 +295,11 @@ tagain:
|
||||
unlinkFid.Cell = aodp->fid.Cell;
|
||||
tvc = (struct vcache *)0;
|
||||
if (!unlinkFid.Fid.Unique) {
|
||||
tvc = afs_LookupVCache(&unlinkFid, &treq, (afs_int32 *)0, WRITE_LOCK,
|
||||
tvc = afs_LookupVCache(&unlinkFid, areq, (afs_int32 *)0, WRITE_LOCK,
|
||||
aodp, aname1);
|
||||
}
|
||||
if (!tvc) /* lookup failed or wasn't called */
|
||||
tvc = afs_GetVCache(&unlinkFid, &treq, (afs_int32 *)0,
|
||||
tvc = afs_GetVCache(&unlinkFid, areq, (afs_int32 *)0,
|
||||
(struct vcache*)0, WRITE_LOCK);
|
||||
|
||||
if (tvc) {
|
||||
@ -334,9 +333,9 @@ tagain:
|
||||
fileFid.Fid.Volume = aodp->fid.Fid.Volume;
|
||||
fileFid.Cell = aodp->fid.Cell;
|
||||
if (!fileFid.Fid.Unique)
|
||||
tvc = afs_LookupVCache(&fileFid, &treq, (afs_int32 *)0, WRITE_LOCK, andp, aname2);
|
||||
tvc = afs_LookupVCache(&fileFid, areq, (afs_int32 *)0, WRITE_LOCK, andp, aname2);
|
||||
else
|
||||
tvc = afs_GetVCache(&fileFid, &treq, (afs_int32 *)0,
|
||||
tvc = afs_GetVCache(&fileFid, areq, (afs_int32 *)0,
|
||||
(struct vcache*)0, WRITE_LOCK);
|
||||
if (tvc && (vType(tvc) == VDIR)) {
|
||||
ObtainWriteLock(&tvc->lock,152);
|
||||
@ -360,16 +359,15 @@ tagain:
|
||||
}
|
||||
code = returnCode;
|
||||
done:
|
||||
code = afs_CheckCode(code, &treq, 25);
|
||||
return code;
|
||||
}
|
||||
|
||||
#ifdef AFS_OSF_ENV
|
||||
afs_rename(fndp, tndp)
|
||||
struct nameidata *fndp, *tndp; {
|
||||
register struct vcache *aodp = VTOAFS(fndp->ni_dvp);
|
||||
struct vcache *aodp = VTOAFS(fndp->ni_dvp);
|
||||
char *aname1 = fndp->ni_dent.d_name;
|
||||
register struct vcache *andp = VTOAFS(tndp->ni_dvp);
|
||||
struct vcache *andp = VTOAFS(tndp->ni_dvp);
|
||||
char *aname2 = tndp->ni_dent.d_name;
|
||||
struct ucred *acred = tndp->ni_cred;
|
||||
#else /* AFS_OSF_ENV */
|
||||
@ -380,14 +378,28 @@ afs_rename(OSI_VC_ARG(aodp), aname1, andp, aname2, npnp, acred)
|
||||
afs_rename(OSI_VC_ARG(aodp), aname1, andp, aname2, acred)
|
||||
#endif
|
||||
OSI_VC_DECL(aodp);
|
||||
register struct vcache *andp;
|
||||
struct vcache *andp;
|
||||
char *aname1, *aname2;
|
||||
struct AFS_UCRED *acred; {
|
||||
#endif
|
||||
register afs_int32 code;
|
||||
struct afs_fakestat_state ofakestate;
|
||||
struct afs_fakestat_state nfakestate;
|
||||
struct vrequest treq;
|
||||
OSI_VC_CONVERT(aodp)
|
||||
|
||||
code = afsrename(aodp, aname1, andp, aname2, acred);
|
||||
code = afs_InitReq(&treq, acred);
|
||||
if (code) return code;
|
||||
afs_InitFakeStat(&ofakestate);
|
||||
afs_InitFakeStat(&nfakestate);
|
||||
code = afs_EvalFakeStat(&aodp, &ofakestate, &treq);
|
||||
if (code) goto done;
|
||||
code = afs_EvalFakeStat(&andp, &nfakestate, &treq);
|
||||
if (code) goto done;
|
||||
code = afsrename(aodp, aname1, andp, aname2, acred, &treq);
|
||||
done:
|
||||
afs_PutFakeStat(&ofakestate);
|
||||
afs_PutFakeStat(&nfakestate);
|
||||
#ifdef AFS_OSF_ENV
|
||||
AFS_RELE(tndp->ni_dvp);
|
||||
if (tndp->ni_vp != NULL) {
|
||||
@ -396,5 +408,6 @@ afs_rename(OSI_VC_ARG(aodp), aname1, andp, aname2, acred)
|
||||
AFS_RELE(fndp->ni_dvp);
|
||||
AFS_RELE(fndp->ni_vp);
|
||||
#endif /* AFS_OSF_ENV */
|
||||
code = afs_CheckCode(code, &treq, 25);
|
||||
return code;
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ afs_symlink
|
||||
struct AFSCallBack CallBack;
|
||||
struct AFSVolSync tsync;
|
||||
struct volume* volp=0;
|
||||
struct afs_fakestat_state fakestate;
|
||||
XSTATS_DECLS
|
||||
OSI_VC_CONVERT(adp)
|
||||
|
||||
@ -79,23 +80,28 @@ afs_symlink
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_SYMLINK, ICL_TYPE_POINTER, adp,
|
||||
ICL_TYPE_STRING, aname);
|
||||
|
||||
if (code = afs_InitReq(&treq, acred))
|
||||
goto done2;
|
||||
|
||||
afs_InitFakeStat(&fakestate);
|
||||
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
|
||||
if (code)
|
||||
goto done;
|
||||
|
||||
if (strlen(aname) > AFSNAMEMAX || strlen(atargetName) > AFSPATHMAX) {
|
||||
code = ENAMETOOLONG;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (afs_IsDynroot(adp)) {
|
||||
code = afs_DynrootVOPSymlink(adp, acred, aname, atargetName);
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (code = afs_InitReq(&treq, acred))
|
||||
goto done2;
|
||||
|
||||
code = afs_VerifyVCache(adp, &treq);
|
||||
if (code) {
|
||||
code = afs_CheckCode(code, &treq, 30);
|
||||
goto done2;
|
||||
code = afs_CheckCode(code, &treq, 30);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/** If the volume is read-only, return error without making an RPC to the
|
||||
@ -103,7 +109,7 @@ afs_symlink
|
||||
*/
|
||||
if ( adp->states & CRO ) {
|
||||
code = EROFS;
|
||||
goto done2;
|
||||
goto done;
|
||||
}
|
||||
|
||||
InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE;
|
||||
@ -223,6 +229,7 @@ afs_symlink
|
||||
afs_PutVCache(tvc, WRITE_LOCK);
|
||||
code = 0;
|
||||
done:
|
||||
afs_PutFakeStat(&fakestate);
|
||||
if ( volp )
|
||||
afs_PutVolume(volp, READ_LOCK);
|
||||
code = afs_CheckCode(code, &treq, 31);
|
||||
@ -342,11 +349,15 @@ afs_readlink(OSI_VC_ARG(avc), auio, acred)
|
||||
register afs_int32 code;
|
||||
struct vrequest treq;
|
||||
register 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_InitReq(&treq, acred)) return code;
|
||||
afs_InitFakeStat(&fakestat);
|
||||
code = afs_EvalFakeStat(&avc, &fakestat, &treq);
|
||||
if (code) goto done;
|
||||
code = afs_VerifyVCache(avc, &treq);
|
||||
if (code) goto done;
|
||||
if (vType(avc) != VLNK) {
|
||||
@ -365,6 +376,7 @@ afs_readlink(OSI_VC_ARG(avc), auio, acred)
|
||||
}
|
||||
ReleaseWriteLock(&avc->lock);
|
||||
done:
|
||||
afs_PutFakeStat(&fakestat);
|
||||
code = afs_CheckCode(code, &treq, 32);
|
||||
return code;
|
||||
}
|
||||
|
@ -725,10 +725,12 @@ afs_closex(afd)
|
||||
afs_int32 flags;
|
||||
int closeDone;
|
||||
afs_int32 code = 0;
|
||||
struct afs_fakestat_state fakestat;
|
||||
|
||||
AFS_STATCNT(afs_closex);
|
||||
/* setup the credentials */
|
||||
if (code = afs_InitReq(&treq, u.u_cred)) return code;
|
||||
afs_InitFakeStat(&fakestat);
|
||||
|
||||
closeDone = 0;
|
||||
/* we're the last one. If we're an AFS vnode, clear the flags,
|
||||
@ -737,6 +739,11 @@ afs_closex(afd)
|
||||
if (afd->f_type == DTYPE_VNODE) {
|
||||
tvc = VTOAFS(afd->f_data);
|
||||
if (IsAfsVnode(AFSTOV(tvc))) {
|
||||
code = afs_EvalFakeStat(&tvc, &fakestat, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return code;
|
||||
}
|
||||
VN_HOLD(AFSTOV(tvc));
|
||||
flags = afd->f_flag & (FSHLOCK | FEXLOCK);
|
||||
afd->f_flag &= ~(FSHLOCK | FEXLOCK);
|
||||
@ -760,6 +767,7 @@ afs_closex(afd)
|
||||
if (!closeDone) {
|
||||
code = vno_close(afd);
|
||||
}
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return code; /* return code from vnode layer */
|
||||
}
|
||||
#endif
|
||||
@ -800,41 +808,44 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
|
||||
afs_int32 aflags;
|
||||
struct AFS_UCRED *acred;
|
||||
{
|
||||
register afs_int32 code, initreq=0;
|
||||
register afs_int32 code;
|
||||
register struct brequest *tb;
|
||||
struct vrequest treq;
|
||||
#ifdef AFS_SGI65_ENV
|
||||
struct flid flid;
|
||||
#endif
|
||||
struct afs_fakestat_state fakestat;
|
||||
OSI_VC_CONVERT(avc)
|
||||
|
||||
AFS_STATCNT(afs_close);
|
||||
afs_Trace2(afs_iclSetp, CM_TRACE_CLOSE, ICL_TYPE_POINTER, avc,
|
||||
ICL_TYPE_INT32, aflags);
|
||||
code = afs_InitReq(&treq, acred);
|
||||
if (code) return code;
|
||||
afs_InitFakeStat(&fakestat);
|
||||
code = afs_EvalFakeStat(&avc, &fakestat, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return code;
|
||||
}
|
||||
#ifdef AFS_SUN5_ENV
|
||||
if (avc->flockCount) {
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
initreq = 1;
|
||||
HandleFlock(avc, LOCK_UN, &treq, 0, 1/*onlymine*/);
|
||||
}
|
||||
#endif
|
||||
#if defined(AFS_SGI_ENV)
|
||||
if (!lastclose)
|
||||
if (!lastclose) {
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#if defined(AFS_SUN_ENV) || defined(AFS_SGI_ENV)
|
||||
if (count > 1) {
|
||||
/* The vfs layer may call this repeatedly with higher "count"; only on the last close (i.e. count = 1) we should actually proceed with the close. */
|
||||
afs_PutFakeStat(&fakestat);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef AFS_SUN5_ENV
|
||||
if (!initreq) {
|
||||
#endif
|
||||
#endif
|
||||
if (code = afs_InitReq(&treq, acred)) return code;
|
||||
#ifdef AFS_SUN5_ENV
|
||||
}
|
||||
#endif
|
||||
#ifndef AFS_SUN5_ENV
|
||||
#if defined(AFS_SGI_ENV)
|
||||
@ -957,6 +968,7 @@ afs_close(OSI_VC_ARG(avc), aflags, acred)
|
||||
afs_remunlink(avc, 1); /* ignore any return code */
|
||||
}
|
||||
#endif
|
||||
afs_PutFakeStat(&fakestat);
|
||||
code = afs_CheckCode(code, &treq, 5);
|
||||
return code;
|
||||
}
|
||||
|
@ -627,7 +627,7 @@ struct vcache {
|
||||
#ifdef AFS_FBSD_ENV
|
||||
struct lock rwlock;
|
||||
#endif
|
||||
afs_int32 parentVnode; /* Parent dir, if a file. */
|
||||
afs_int32 parentVnode; /* Parent dir, if a file. */
|
||||
afs_int32 parentUnique;
|
||||
struct VenusFid *mvid; /* Either parent dir (if root) or root (if mt pt) */
|
||||
char *linkData; /* Link data if a symlink. */
|
||||
@ -1181,5 +1181,18 @@ extern int afs_norefpanic;
|
||||
#endif /* AFS_SGI62_ENV */
|
||||
#endif
|
||||
|
||||
/* fakestat support: opaque storage for afs_EvalFakeStat to remember
|
||||
* what vcache should be released.
|
||||
*/
|
||||
struct afs_fakestat_state {
|
||||
char valid;
|
||||
char did_eval;
|
||||
char need_release;
|
||||
char nonblock;
|
||||
struct vcache *root_vp;
|
||||
};
|
||||
|
||||
extern int afs_fakestat_enable;
|
||||
|
||||
#endif /* _AFS_H_ */
|
||||
|
||||
|
@ -662,6 +662,10 @@ long parm, parm2, parm3, parm4, parm5, parm6;
|
||||
else if (parm == AFSOP_SET_DYNROOT) {
|
||||
code = afs_SetDynrootEnable(parm2);
|
||||
}
|
||||
else if (parm == AFSOP_SET_FAKESTAT) {
|
||||
afs_fakestat_enable = parm2;
|
||||
code = 0;
|
||||
}
|
||||
else
|
||||
code = EINVAL;
|
||||
|
||||
|
@ -1036,7 +1036,7 @@ afs_syscall_pioctl(path, com, cmarg, follow)
|
||||
|
||||
|
||||
afs_HandlePioctl(avc, acom, ablob, afollow, acred)
|
||||
register struct vcache *avc;
|
||||
struct vcache *avc;
|
||||
afs_int32 acom;
|
||||
struct AFS_UCRED **acred;
|
||||
register struct afs_ioctl *ablob;
|
||||
@ -1049,11 +1049,20 @@ afs_HandlePioctl(avc, acom, ablob, afollow, acred)
|
||||
char *inData, *outData;
|
||||
int (*(*pioctlSw))();
|
||||
int pioctlSwSize;
|
||||
struct afs_fakestat_state fakestate;
|
||||
|
||||
afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
|
||||
ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
|
||||
AFS_STATCNT(HandlePioctl);
|
||||
if (code = afs_InitReq(&treq, *acred)) return code;
|
||||
afs_InitFakeStat(&fakestate);
|
||||
if (avc) {
|
||||
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
|
||||
if (code) {
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
device = (acom & 0xff00) >> 8;
|
||||
switch (device) {
|
||||
case 'V': /* Original pioctl's */
|
||||
@ -1065,11 +1074,13 @@ afs_HandlePioctl(avc, acom, ablob, afollow, acred)
|
||||
pioctlSwSize = sizeof(CpioctlSw);
|
||||
break;
|
||||
default:
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return EINVAL;
|
||||
}
|
||||
function = acom & 0xff;
|
||||
if (function >= (pioctlSwSize / sizeof(char *))) {
|
||||
return EINVAL; /* out of range */
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return EINVAL; /* out of range */
|
||||
}
|
||||
inSize = ablob->in_size;
|
||||
if (inSize >= PIGGYSIZE) return E2BIG;
|
||||
@ -1079,8 +1090,9 @@ afs_HandlePioctl(avc, acom, ablob, afollow, acred)
|
||||
}
|
||||
else code = 0;
|
||||
if (code) {
|
||||
osi_FreeLargeSpace(inData);
|
||||
return code;
|
||||
osi_FreeLargeSpace(inData);
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return code;
|
||||
}
|
||||
outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
|
||||
outSize = 0;
|
||||
@ -1096,6 +1108,7 @@ afs_HandlePioctl(avc, acom, ablob, afollow, acred)
|
||||
AFS_COPYOUT(outData, ablob->out, outSize, code);
|
||||
}
|
||||
osi_FreeLargeSpace(outData);
|
||||
afs_PutFakeStat(&fakestate);
|
||||
return afs_CheckCode(code, &treq, 41);
|
||||
}
|
||||
|
||||
@ -1719,7 +1732,7 @@ static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
|
||||
code = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
if (vType(tvc) != VLNK) {
|
||||
if (tvc->mvstat != 1) {
|
||||
afs_PutVCache(tvc, WRITE_LOCK);
|
||||
code = EINVAL;
|
||||
goto out;
|
||||
@ -2504,7 +2517,7 @@ static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
|
||||
afs_PutDCache(tdc);
|
||||
goto out;
|
||||
}
|
||||
if (vType(tvc) != VLNK) {
|
||||
if (tvc->mvstat != 1) {
|
||||
afs_PutDCache(tdc);
|
||||
afs_PutVCache(tvc, WRITE_LOCK);
|
||||
code = EINVAL;
|
||||
@ -3703,7 +3716,7 @@ static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
|
||||
code = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
if (vType(tvc) != VLNK) {
|
||||
if (tvc->mvstat != 1) {
|
||||
afs_PutVCache(tvc, WRITE_LOCK);
|
||||
code = EINVAL;
|
||||
goto out;
|
||||
|
@ -1542,9 +1542,16 @@ afs_ProcessFS(avc, astat, areq)
|
||||
avc->m.Mode |= S_IFDIR;
|
||||
}
|
||||
else if (astat->FileType == SymbolicLink) {
|
||||
vSetType(avc, VLNK);
|
||||
avc->m.Mode |= S_IFLNK;
|
||||
if ((avc->m.Mode & 0111) == 0) avc->mvstat = 1;
|
||||
if (afs_fakestat_enable && (avc->m.Mode & 0111) == 0) {
|
||||
vSetType(avc, VDIR);
|
||||
avc->m.Mode |= S_IFDIR;
|
||||
} else {
|
||||
vSetType(avc, VLNK);
|
||||
avc->m.Mode |= S_IFLNK;
|
||||
}
|
||||
if ((avc->m.Mode & 0111) == 0) {
|
||||
avc->mvstat = 1;
|
||||
}
|
||||
}
|
||||
avc->anyAccess = astat->AnonymousAccess;
|
||||
#ifdef badidea
|
||||
|
@ -240,6 +240,7 @@ static int enable_process_stats = 0; /* enable rx stats */
|
||||
static int enable_afsdb = 0; /* enable AFSDB support */
|
||||
#endif
|
||||
static int enable_dynroot = 0; /* enable dynroot support */
|
||||
static int enable_fakestat = 0; /* enable fakestat support */
|
||||
#ifdef notdef
|
||||
static int inodes = 60; /* VERY conservative, but has to be */
|
||||
#endif
|
||||
@ -1326,6 +1327,10 @@ mainproc(as, arock)
|
||||
/* -dynroot */
|
||||
enable_dynroot = 1;
|
||||
}
|
||||
if (as->parms[27].items) {
|
||||
/* -fakestat */
|
||||
enable_fakestat = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pull out all the configuration info for the workstation's AFS cache and
|
||||
@ -1565,6 +1570,14 @@ mainproc(as, arock)
|
||||
printf("%s: Error enabling dynroot support.\n", rn);
|
||||
}
|
||||
|
||||
if (enable_fakestat) {
|
||||
if (afsd_verbose)
|
||||
printf("%s: Enabling fakestat support in kernel.\n", rn);
|
||||
code = call_syscall(AFSOP_SET_FAKESTAT, 1);
|
||||
if (code)
|
||||
printf("%s: Error enabling fakestat support.\n", rn);
|
||||
}
|
||||
|
||||
/* Initialize AFS daemon threads. */
|
||||
if (afsd_verbose)
|
||||
printf("%s: Forking AFS daemon.\n", rn);
|
||||
@ -1918,6 +1931,7 @@ char **argv; {
|
||||
), "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");
|
||||
return (cmd_Dispatch(argc, argv));
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define AFSOP_AFSDB_HANDLER 30 /* userspace AFSDB lookup handler */
|
||||
#define AFSOP_SET_DYNROOT 31 /* enable/disable dynroot support */
|
||||
#define AFSOP_ADDCELLALIAS 32 /* create alias for existing cell */
|
||||
#define AFSOP_SET_FAKESTAT 33 /* enable/disable fakestat support */
|
||||
|
||||
/* The range 20-30 is reserved for AFS system offsets in the afs_syscall */
|
||||
#define AFSCALL_PIOCTL 20
|
||||
|
Loading…
Reference in New Issue
Block a user