#endif
extern struct vcache *afs_globalVp;
+extern afs_rwlock_t afs_xvcache;
extern struct dentry_operations *afs_dops;
#if defined(AFS_LINUX24_ENV)
int len;
afs_size_t origOffset, tlen;
cred_t *credp = crref();
+ struct afs_fakestat_state fakestat;
AFS_GLOCK();
AFS_STATCNT(afs_readdir);
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;
}
tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
len = tlen;
if (!tdc) {
+ afs_PutFakeStat(&fakestat);
AFS_GUNLOCK();
return -ENOENT;
}
afid.Fid.Unique=ntohl(de->fid.vunique);
if ((avc->states & CForeign) == 0 &&
(ntohl(de->fid.vnode) & 1)) {
+ type=DT_DIR;
} else if ((tvc=afs_FindVCache(&afid,0,0,0,0))) {
if (tvc->mvstat) {
type=DT_DIR;
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc);
ReleaseReadLock(&avc->lock);
+ afs_PutFakeStat(&fakestat);
AFS_GUNLOCK();
return 0;
}
cred_t *credp;
struct vrequest treq;
struct vcache *vcp = ITOAFS(dp->d_inode);
+ struct vcache *rootvp = NULL;
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, 0, 0);
+ ReleaseSharedLock(&afs_xvcache);
+ }
+
#ifdef AFS_LINUX24_ENV
lock_kernel();
#endif
/* Make this a fast path (no crref), since it's called so often. */
if (vcp->states & CStatd) {
- if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
+ if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
check_bad_parent(dp); /* check and correct mvid */
- vcache2inode(vcp);
+ if (rootvp)
+ vcache2fakeinode(rootvp, vcp);
+ else
+ vcache2inode(vcp);
#ifdef AFS_LINUX24_ENV
unlock_kernel();
#endif
+ if (rootvp) afs_PutVCache(rootvp);
AFS_GUNLOCK();
return 0;
}
if (!vcp || !parentvcp)
goto done;
+ /* If it is the AFS root, then there's no chance it needs
+ revalidating */
+ if (vcp == afs_globalVp) {
+ bad_dentry = 0;
+ goto done;
+ }
+
if (code = afs_InitReq(&treq, credp))
goto done;
unsigned long timeout = 3*HZ; /* 3 seconds */
-if (!ip)
+ if (!ip)
printk("negative dentry: %s\n", dp->d_name.name);
if (!(flags & LOOKUP_CONTINUE)) {
/* afs_dentry_iput */
static void afs_dentry_iput(struct dentry *dp, struct inode *ip)
{
+ afs_Trace3(afs_iclSetp, CM_TRACE_DENTRYIPUT,
+ ICL_TYPE_POINTER, ip,
+ ICL_TYPE_STRING, dp->d_parent->d_name.name,
+ ICL_TYPE_STRING, dp->d_name.name);
+
osi_iput(ip);
}
+static int afs_dentry_delete(struct dentry *dp)
+{
+ afs_Trace3(afs_iclSetp, CM_TRACE_DENTRYDELETE, ICL_TYPE_POINTER,
+ dp->d_inode, ICL_TYPE_STRING, dp->d_parent->d_name.name,
+ ICL_TYPE_STRING, dp->d_name.name);
+
+ if (dp->d_inode && (ITOAFS(dp->d_inode)->states & CUnlinked))
+ return 1; /* bad inode? */
+
+ return 0;
+}
+
#if defined(AFS_LINUX24_ENV)
struct dentry_operations afs_dentry_operations = {
d_revalidate: afs_linux_dentry_revalidate,
d_iput: afs_dentry_iput,
+ d_delete: afs_dentry_delete,
};
struct dentry_operations *afs_dops = &afs_dentry_operations;
#else
afs_linux_dentry_revalidate, /* d_validate(struct dentry *) */
NULL, /* d_hash */
NULL, /* d_compare */
- NULL, /* d_delete(struct dentry *) */
+ afs_dentry_delete, /* d_delete(struct dentry *) */
NULL, /* d_release(struct dentry *) */
afs_dentry_iput /* d_iput(struct dentry *, struct inode *) */
};
int code;
cred_t *credp = crref();
const char *name = dp->d_name.name;
- int putback = 0;
AFS_GLOCK();
code = afs_remove(ITOAFS(dip), name, credp);