static inline int
afs_linux_VerifyVCache(struct vcache *avc, cred_t **retcred) {
cred_t *credp = NULL;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
int code;
if (avc->f.states & CStatd) {
credp = crref();
- code = afs_InitReq(&treq, credp);
- if (code == 0)
- code = afs_VerifyVCache2(avc, &treq);
+ code = afs_CreateReq(&treq, credp);
+ if (code == 0) {
+ code = afs_VerifyVCache2(avc, treq);
+ afs_DestroyReq(treq);
+ }
if (retcred != NULL)
*retcred = credp;
#endif
{
struct vcache *avc = VTOAFS(FILE_INODE(fp));
- struct vrequest treq;
+ struct vrequest *treq = NULL;
struct dcache *tdc;
int code;
int offset;
AFS_GLOCK();
AFS_STATCNT(afs_readdir);
- code = afs_convert_code(afs_InitReq(&treq, credp));
+ code = afs_convert_code(afs_CreateReq(&treq, credp));
crfree(credp);
if (code)
goto out1;
afs_InitFakeStat(&fakestat);
- code = afs_convert_code(afs_EvalFakeStat(&avc, &fakestat, &treq));
+ code = afs_convert_code(afs_EvalFakeStat(&avc, &fakestat, treq));
if (code)
goto out;
/* update the cache entry */
tagain:
- code = afs_convert_code(afs_VerifyVCache2(avc, &treq));
+ code = afs_convert_code(afs_VerifyVCache2(avc, treq));
if (code)
goto out;
/* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
+ tdc = afs_GetDCache(avc, (afs_size_t) 0, treq, &origOffset, &tlen, 1);
len = tlen;
if (!tdc) {
code = -ENOENT;
out:
afs_PutFakeStat(&fakestat);
+ afs_DestroyReq(treq);
out1:
AFS_GUNLOCK();
return code;
afs_linux_flush(struct file *fp)
#endif
{
- struct vrequest treq;
+ struct vrequest *treq = NULL;
struct vcache *vcp;
cred_t *credp;
int code;
credp = crref();
vcp = VTOAFS(FILE_INODE(fp));
- code = afs_InitReq(&treq, credp);
+ code = afs_CreateReq(&treq, credp);
if (code)
goto out;
/* If caching is bypassed for this file, or globally, just return 0 */
UpgradeSToWLock(&vcp->lock, 536);
if (!AFS_IS_DISCONNECTED) {
code = afs_StoreAllSegments(vcp,
- &treq,
+ treq,
AFS_SYNC | AFS_LASTSTORE);
} else {
afs_DisconAddDirty(vcp, VDisconWriteOsiFlush, 1);
}
ConvertWToSLock(&vcp->lock);
}
- code = afs_CheckCode(code, &treq, 54);
+ code = afs_CheckCode(code, treq, 54);
ReleaseSharedLock(&vcp->lock);
out:
+ afs_DestroyReq(treq);
AFS_DISCON_UNLOCK();
AFS_GUNLOCK();
return err;
}
+static afs_uint32
+parent_vcache_dv(struct inode *inode, cred_t *credp)
+{
+ int free_cred = 0;
+ struct vcache *pvcp;
+
+ /*
+ * If parent is a mount point and we are using fakestat, we may need
+ * to look at the fake vcache entry instead of what the vfs is giving
+ * us. The fake entry is the one with the useful DataVersion.
+ */
+ pvcp = VTOAFS(inode);
+ if (pvcp->mvstat == 1 && afs_fakestat_enable) {
+ struct vrequest treq;
+ struct afs_fakestat_state fakestate;
+
+ if (!credp) {
+ credp = crref();
+ free_cred = 1;
+ }
+ afs_InitReq(&treq, credp);
+ afs_InitFakeStat(&fakestate);
+ afs_TryEvalFakeStat(&pvcp, &fakestate, &treq);
+ if (free_cred)
+ crfree(credp);
+ afs_PutFakeStat(&fakestate);
+ }
+ return hgetlo(pvcp->f.m.DataVersion);
+}
+
/* Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
* In kernels 2.2.10 and above, we are passed an additional flags var which
* may have either the LOOKUP_FOLLOW OR LOOKUP_DIRECTORY set in which case
struct afs_fakestat_state fakestate;
int locked = 0;
int force_drop = 0;
+ afs_uint32 parent_dv;
#ifdef LOOKUP_RCU
/* We don't support RCU path walking */
parent = dget_parent(dp);
pvcp = VTOAFS(parent->d_inode);
- if ((vcp->mvstat == 1) || (vcp->mvstat == 2)) { /* need to lock */
+ if ((vcp->mvstat == 1) || (vcp->mvstat == 2) ||
+ (pvcp->mvstat == 1 && afs_fakestat_enable)) { /* need to lock */
credp = crref();
AFS_GLOCK();
locked = 1;
if (vcp->mvid && (vcp->f.states & CMValid)) {
int tryEvalOnly = 0;
int code = 0;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
- code = afs_InitReq(&treq, credp);
- if (
- (strcmp(dp->d_name.name, ".directory") == 0)) {
+ code = afs_CreateReq(&treq, credp);
+ if (code) {
+ dput(parent);
+ goto bad_dentry;
+ }
+ if ((strcmp(dp->d_name.name, ".directory") == 0)) {
tryEvalOnly = 1;
}
if (tryEvalOnly)
- code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
+ code = afs_TryEvalFakeStat(&vcp, &fakestate, treq);
else
- code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
+ code = afs_EvalFakeStat(&vcp, &fakestate, treq);
+ afs_DestroyReq(treq);
if ((tryEvalOnly && vcp->mvstat == 1) || code) {
/* a mount point, not yet replaced by its directory */
dput(parent);
}
#endif
+ parent_dv = parent_vcache_dv(parent->d_inode, credp);
/* If the parent's DataVersion has changed or the vnode
* is longer valid, we need to do a full lookup. VerifyVCache
* isn't enough since the vnode may have been renamed.
*/
- if ((!locked) && (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd)) ) {
+ if ((!locked) && (parent_dv > dp->d_time || !(vcp->f.states & CStatd)) ) {
credp = crref();
AFS_GLOCK();
locked = 1;
}
- if (locked && (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd))) {
+ if (locked && (parent_dv > dp->d_time || !(vcp->f.states & CStatd))) {
int code;
code = afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
}
vattr2inode(AFSTOV(vcp), &vattr);
- dp->d_time = hgetlo(pvcp->f.m.DataVersion);
+ dp->d_time = parent_dv;
}
/* should we always update the attributes at this point? */
#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
dp->d_op = &afs_dentry_operations;
#endif
- dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
+ dp->d_time = parent_vcache_dv(dip, credp);
d_instantiate(dp, ip);
}
AFS_GUNLOCK();
#if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP)
dp->d_op = &afs_dentry_operations;
#endif
- dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
+ dp->d_time = parent_vcache_dv(dip, credp);
+
AFS_GUNLOCK();
if (ip && S_ISDIR(ip->i_mode)) {
if (AFS_CHUNKOFFSET(offset) == 0) {
struct dcache *tdc;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
cred_t *credp;
credp = crref();
AFS_GLOCK();
- code = afs_InitReq(&treq, credp);
+ code = afs_CreateReq(&treq, credp);
if (!code && !NBObtainWriteLock(&avc->lock, 534)) {
tdc = afs_FindDCache(avc, offset);
if (tdc) {
if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, credp, &treq);
+ afs_PrefetchChunk(avc, tdc, credp, treq);
afs_PutDCache(tdc);
}
ReleaseWriteLock(&avc->lock);
}
+ afs_DestroyReq(treq);
AFS_GUNLOCK();
crfree(credp);
}
static inline int
afs_linux_dopartialwrite(struct vcache *avc, cred_t *credp) {
- struct vrequest treq;
+ struct vrequest *treq = NULL;
int code = 0;
- if (!afs_InitReq(&treq, credp))
- code = afs_DoPartialWrite(avc, &treq);
+ if (!afs_CreateReq(&treq, credp)) {
+ code = afs_DoPartialWrite(avc, treq);
+ afs_DestroyReq(treq);
+ }
return afs_convert_code(code);
}