linux-dcache-inconsistency-fix-20020115

minor rework on a patch from Ted Anderson (ota@transarc.com) to
fit OpenAFS
This commit is contained in:
Chas Williams 2002-01-16 02:08:43 +00:00 committed by Derrick Brashear
parent d581ab206e
commit 4860f8cb15

View File

@ -28,6 +28,7 @@ RCSID("$Header$");
#include "../afs/sysincludes.h"
#include "../afs/afsincludes.h"
#include "../afs/afs_stats.h"
#include "../afs/afs_osidnlc.h"
#include "../h/mm.h"
#include "../h/pagemap.h"
#if defined(AFS_LINUX24_ENV)
@ -781,6 +782,82 @@ static int afs_linux_revalidate(struct dentry *dp)
return -code ;
}
/* 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
* we are advised to follow the entry if it is a link or to make sure that
* it is a directory. But since the kernel itself checks these possibilities
* later on, we shouldn't have to do it until later. Perhaps in the future..
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
static int afs_linux_dentry_revalidate(struct dentry *dp, int flags)
#else
static int afs_linux_dentry_revalidate(struct dentry *dp)
#endif
{
char *name;
cred_t *credp = crref();
struct vrequest treq;
struct vcache *lookupvcp = NULL;
int code, bad_dentry = 1;
struct sysname_info sysState;
struct vcache *vcp = (struct vcache*) dp->d_inode;
struct vcache *parentvcp = (struct vcache*) dp->d_parent->d_inode;
AFS_GLOCK();
/* If it's a negative dentry, then there's nothing to do. */
if (!vcp || !parentvcp)
goto done;
if (code = afs_InitReq(&treq, credp))
goto done;
Check_AtSys(parentvcp, dp->d_name.name, &sysState, &treq);
name = sysState.name;
/* 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;
goto done;
}
/* A DNLC lookup failure cannot be trusted. Try a real lookup */
code = afs_lookup(parentvcp, name, &lookupvcp, credp);
/* Verify that the dentry does not point to an old inode */
if (vcp != lookupvcp)
goto done;
bad_dentry = 0;
done:
/* Clean up */
if (lookupvcp)
afs_PutVCache(lookupvcp, WRITE_LOCK);
if (sysState.allocked)
osi_FreeLargeSpace(name);
AFS_GUNLOCK();
crfree(credp);
if (bad_dentry) {
shrink_dcache_parent(dp);
d_drop(dp);
}
return !bad_dentry;
}
#ifdef notdef
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
static int afs_linux_dentry_revalidate(struct dentry *dp, int flags)
#else
@ -794,6 +871,9 @@ static int afs_linux_dentry_revalidate(struct dentry *dp)
unsigned long timeout = 3*HZ; /* 3 seconds */
if (!ip)
printk("negative dentry: %s\n", dp->d_name.name);
if (!(flags & LOOKUP_CONTINUE)) {
long diff = CURRENT_TIME - dp->d_parent->d_inode->i_mtime;
@ -810,6 +890,7 @@ static int afs_linux_dentry_revalidate(struct dentry *dp)
out_bad:
return 0;
}
#endif
/* afs_dentry_iput */
static void afs_dentry_iput(struct dentry *dp, struct inode *ip)
@ -927,17 +1008,17 @@ int afs_linux_lookup(struct inode *dip, struct dentry *dp)
ip->i_data.a_ops = &afs_symlink_aops;
ip->i_mapping = &ip->i_data;
} else
printk("afs_linux_lookup: FIXME\n");
printk("afs_linux_lookup: ip->i_mode 0x%x dp->d_name.name %s code %d\n", ip->i_mode, dp->d_name.name, code);
#else
if (S_ISDIR(ip->i_mode))
ip->i_op = &afs_dir_iops;
else if (S_ISLNK(ip->i_mode))
ip->i_op = &afs_symlink_iops;
#endif
}
dp->d_time = jiffies;
dp->d_op = afs_dops;
d_add(dp, (struct inode*)vcp);
}
AFS_GUNLOCK();
crfree(credp);
@ -985,27 +1066,11 @@ int afs_linux_unlink(struct inode *dip, struct dentry *dp)
const char *name = dp->d_name.name;
int putback = 0;
if (!list_empty(&dp->d_hash)) {
d_drop(dp);
/* Install a definite non-existence if we're the only user. */
#if defined(AFS_LINUX24_ENV)
if (atomic_read(&dp->d_count) == 1)
#else
if (dp->d_count == 1)
#endif
putback = 1;
}
AFS_GLOCK();
code = afs_remove((struct vcache*)dip, name, credp);
AFS_GUNLOCK();
if (!code) {
d_delete(dp);
if (putback) {
dp->d_time = jiffies;
d_add(dp, NULL); /* means definitely does _not_ exist */
}
}
if (!code)
d_drop(dp);
crfree(credp);
return -code;
}
@ -1055,6 +1120,7 @@ int afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
dp->d_time = jiffies;
d_instantiate(dp, (struct inode*)tvcp);
}
AFS_GUNLOCK();
crfree(credp);
return -code;
@ -1078,7 +1144,7 @@ int afs_linux_rmdir(struct inode *dip, struct dentry *dp)
}
if (!code) {
d_delete(dp);
d_drop(dp);
}
AFS_GUNLOCK();