linux-sysname-list-sys-links-resolve-dentry-20031109

without this, if you're in a directory that the second or later entry in a
sysname list resolved to, pwd returns ESTALE. force the true path to have its
dentry cached.
This commit is contained in:
Derrick Brashear 2003-11-10 01:36:09 +00:00
parent c5110942b9
commit 2d3fda8c82

View File

@ -957,43 +957,6 @@ afs_linux_dentry_revalidate(struct dentry *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
static int
afs_linux_dentry_revalidate(struct dentry *dp)
#endif
{
int code;
cred_t *credp;
struct vrequest treq;
struct inode *ip = AFSTOI(dp->d_inode);
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;
if (diff < 15 * 60)
timeout = 0;
}
if (time_after(jiffies, dp->d_time + timeout))
goto out_bad;
out_valid:
return 1;
out_bad:
return 0;
}
#endif
/* afs_dentry_iput */
static void
afs_dentry_iput(struct dentry *dp, struct inode *ip)
@ -1109,6 +1072,8 @@ afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
return -code;
}
#define AFS_EQ_ATSYS(name) (((name)[0]=='@')&&((name)[1]=='s')&&((name)[2]=='y')&&((name)[3]=='s')&&(!(name)[4]))
/* afs_linux_lookup */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
struct dentry *
@ -1122,9 +1087,30 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
cred_t *credp = crref();
struct vcache *vcp = NULL;
const char *comp = dp->d_name.name;
AFS_GLOCK();
code = afs_lookup(ITOAFS(dip), comp, &vcp, credp);
char *name = NULL;
struct sysname_info sysState;
struct qstr qstr;
struct vrequest treq;
sysState.allocked = 0;
AFS_GLOCK();
/* In order that we not get ESTALE on @sys links that resolve
into the 2nd or later item in an @sys list, resolve it ourselves
and force a lookup of the actual match here. The real directory
thus gets the dentry. */
if (AFS_EQ_ATSYS(comp) && !afs_InitReq(&treq, credp)) {
Check_AtSys(ITOAFS(dip), comp, &sysState, &treq);
name = sysState.name;
code = afs_lookup(ITOAFS(dip), name, &vcp, credp);
while (code == ENOENT && Next_AtSys(ITOAFS(dip), &treq, &sysState)) {
code = afs_lookup(ITOAFS(dip), name, &vcp, credp);
}
} else
code = afs_lookup(ITOAFS(dip), comp, &vcp, credp);
if (vcp) {
struct inode *ip = AFSTOI(vcp);
/* Reset ops if symlink or directory. */
@ -1155,6 +1141,27 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
dp->d_op = afs_dops;
d_add(dp, AFSTOI(vcp));
#if 0
/* Set up a dentry alias. Should we be doing this for @sys?
You only get one for a directory, which would be fine,
@sys would only map to one at a time, but it's unclear
that this is consistent behavior. */
if (AFS_EQ_ATSYS(comp) && sysState.allocked) {
int result;
struct dentry *dentry;
qstr.name = name;
qstr.len = strlen(name);
qstr.hash = full_name_hash(name, qstr.len);
result = d_lookup(dp->d_parent, &qstr);
if (!result) {
dentry = d_alloc(dp->d_parent, &qstr);
if (dentry)
d_instantiate(dentry, AFSTOI(vcp));
}
}
#endif
AFS_GUNLOCK();
crfree(credp);