X-Git-Url: https://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2Fafs%2FLINUX%2Fosi_vnodeops.c;h=d527dc96e2991fa2855f58342ea6acd5581b91fd;hp=b7cae5aa12d6e7a021af02e28e4cd9704e04cee5;hb=389473032cf0b200c2c39fd5ace108bdc05c9d97;hpb=5cc3aec78a4329885b450c15ce228fa6fb413fdf diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index b7cae5a..d527dc9 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1125,6 +1125,7 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags) int valid; struct afs_fakestat_state fakestate; int locked = 0; + int force_drop = 0; #ifdef LOOKUP_RCU /* We don't support RCU path walking */ @@ -1209,9 +1210,14 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags) } if (locked && (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd))) { - afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp); + int code; + + code = afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp); if (!tvc || tvc != vcp) { dput(parent); + /* Force unhash if name is known not to exist. */ + if (code == ENOENT) + force_drop = 1; goto bad_dentry; } @@ -1262,8 +1268,18 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags) if (credp) crfree(credp); - if (!valid) - d_invalidate(dp); + if (!valid) { + /* + * If we had a negative lookup for the name we want to forcibly + * unhash the dentry. + * Otherwise use d_invalidate which will not unhash it if still in use. + */ + if (force_drop) { + shrink_dcache_parent(dp); + d_drop(dp); + } else + d_invalidate(dp); + } return valid;