int valid;
struct afs_fakestat_state fakestate;
int locked = 0;
+ int force_drop = 0;
#ifdef LOOKUP_RCU
/* We don't support RCU path walking */
}
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;
}
crfree(credp);
if (!valid) {
- shrink_dcache_parent(dp);
- d_drop(dp);
+ /*
+ * 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;
bad_dentry:
VATTR_NULL(&vattr);
AFS_GLOCK();
- code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp);
+ code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, NULL,
+ credp);
AFS_GUNLOCK();
crfree(credp);
return afs_convert_code(code);