From 2d3fda8c82c24b01537ed10fe614ce5eea130754 Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Mon, 10 Nov 2003 01:36:09 +0000 Subject: [PATCH] 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. --- src/afs/LINUX/osi_vnodeops.c | 85 +++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 0e0ec36b18..413a893ca7 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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);