#include "afs/sysincludes.h"
#include "afsincludes.h"
#include "afs/afs_stats.h"
-#include "afs/afs_osidnlc.h"
#include "h/mm.h"
#ifdef HAVE_MM_INLINE_H
#include "h/mm_inline.h"
afs_linux_dentry_revalidate(struct dentry *dp)
#endif
{
- char *name = NULL;
- cred_t *credp = crref();
+ cred_t *credp = NULL;
struct vrequest treq;
- struct vcache *lookupvcp = NULL;
- int code, bad_dentry = 1;
- struct sysname_info sysState;
- struct vcache *vcp, *parentvcp;
-
- sysState.allocked = 0;
+ int code, bad_dentry;
+ struct vcache *vcp, *pvcp;
#ifdef AFS_LINUX24_ENV
lock_kernel();
AFS_GLOCK();
vcp = ITOAFS(dp->d_inode);
- parentvcp = ITOAFS(dp->d_parent->d_inode);
-
- /* If it's a negative dentry, then there's nothing to do. */
- if (!vcp || !parentvcp)
- goto done;
+ pvcp = ITOAFS(dp->d_parent->d_inode); /* dget_parent()? */
- /* If it is the AFS root, then there's no chance it needs
- * revalidating */
- if (vcp == afs_globalVp) {
- bad_dentry = 0;
+ /* If it's a negative dentry, it's never valid */
+ if (!vcp || !pvcp) {
+ bad_dentry = 1;
goto done;
}
- if ((code = afs_InitReq(&treq, credp)))
- goto done;
+ /* If it's the AFS root no chance it needs revalidating */
+ if (vcp == afs_globalVp)
+ goto good_dentry;
- Check_AtSys(parentvcp, dp->d_name.name, &sysState, &treq);
- name = sysState.name;
+ /* parent's DataVersion changed? */
+ if (hgetlo(pvcp->m.DataVersion) > dp->d_time) {
+ vcp->states &= ~CStatd; /* force afs_VerifyVCache() to go to the server */
+ }
- /* First try looking up the DNLC */
- if ((lookupvcp = osi_dnlc_lookup(parentvcp, name, WRITE_LOCK))) {
- /* Verify that the dentry does not point to an old inode */
- if (vcp != lookupvcp)
- goto done;
- /* Check and correct mvid */
- if (*name != '/' && vcp->mvstat == 2)
- check_bad_parent(dp);
- vcache2inode(vcp);
- bad_dentry = 0;
+ /* Get a validated vcache entry */
+ credp = crref();
+ code = afs_InitReq(&treq, credp);
+ if (code) {
+ bad_dentry = 2;
+ goto done;
+ }
+ code = afs_VerifyVCache(vcp, &treq);
+ if (code) {
+ bad_dentry = 3;
goto done;
}
- /* A DNLC lookup failure cannot be trusted. Try a real lookup.
- Make sure to try the real name and not the @sys expansion;
- afs_lookup will expand @sys itself. */
-
- code = afs_lookup(parentvcp, dp->d_name.name, &lookupvcp, credp);
+ /* If we aren't the last looker, verify access */
+ if (vcp->last_looker != treq.uid) {
+ if (!afs_AccessOK(vcp, (vType(vcp) == VREG) ? PRSFS_READ : PRSFS_LOOKUP, &treq, CHECK_MODE_BITS)) {
+ bad_dentry = 5;
+ goto done;
+ }
- /* Verify that the dentry does not point to an old inode */
- if (vcp != lookupvcp)
- goto done;
+ vcp->last_looker = treq.uid;
+ }
+ good_dentry:
bad_dentry = 0;
done:
/* Clean up */
- if (lookupvcp)
- afs_PutVCache(lookupvcp);
- if (sysState.allocked)
- osi_FreeLargeSpace(name);
-
AFS_GUNLOCK();
-
if (bad_dentry) {
shrink_dcache_parent(dp);
d_drop(dp);
}
-
#ifdef AFS_LINUX24_ENV
unlock_kernel();
#endif
- crfree(credp);
+ if (credp)
+ crfree(credp);
return !bad_dentry;
}
static void
afs_dentry_iput(struct dentry *dp, struct inode *ip)
{
- int isglock;
-
- if (ICL_SETACTIVE(afs_iclSetp)) {
- isglock = ISAFS_GLOCK();
- if (!isglock) AFS_GLOCK();
- 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);
- if (!isglock) AFS_GUNLOCK();
- }
-
osi_iput(ip);
}
#endif
static int
afs_dentry_delete(struct dentry *dp)
{
- int isglock;
- if (ICL_SETACTIVE(afs_iclSetp)) {
- isglock = ISAFS_GLOCK();
- if (!isglock) AFS_GLOCK();
- 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 (!isglock) AFS_GUNLOCK();
- }
-
if (dp->d_inode && (ITOAFS(dp->d_inode)->states & CUnlinked))
return 1; /* bad inode? */
#endif
dp->d_op = &afs_dentry_operations;
+ dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
d_instantiate(dp, ip);
}
#endif
}
dp->d_op = &afs_dentry_operations;
+ dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
d_add(dp, AFSTOI(vcp));
#if defined(AFS_LINUX26_ENV)
}
AFS_GUNLOCK();
- if (!code)
+ if (!code) {
+ __dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
d_move(dp, __dp);
+ }
dput(__dp);
goto out;
tvcp->v.v_fop = &afs_dir_fops;
#endif
dp->d_op = &afs_dentry_operations;
+ dp->d_time = hgetlo(ITOAFS(dip)->m.DataVersion);
d_instantiate(dp, AFSTOI(tvcp));
}