[OpenAFS-devel] Linux 2.6.12 kernel BUG at fs/namei.c:1189
chas williams - CONTRACTOR
chas@cmf.nrl.navy.mil
Mon, 12 Dec 2005 20:14:45 -0500
In message <877jab34qc.fsf@windlord.stanford.edu>,Russ Allbery writes:
>This sounds fairly credible to me, although I don't really know how to fix
>it. :) I'm surprised that more people haven't run into this. I mv mount
>points all the time; maybe I'm weird?
some earlier versions of afs didnt worry about how many dentries were
hanging off a directory inode. anyway, try this. do_rename() seems
to do a lookup/revalidation before it does the rename. this patch just
drops the existing dentry in favor of a more "relative" dentry.
Index: src/afs/LINUX/osi_vnodeops.c
===================================================================
RCS file: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v
retrieving revision 1.121
diff -u -u -r1.121 osi_vnodeops.c
--- src/afs/LINUX/osi_vnodeops.c 15 Oct 2005 15:51:09 -0000 1.121
+++ src/afs/LINUX/osi_vnodeops.c 13 Dec 2005 01:04:30 -0000
@@ -879,11 +882,9 @@
afs_linux_lookup(struct inode *dip, struct dentry *dp)
#endif
{
- struct vattr vattr;
cred_t *credp = crref();
struct vcache *vcp = NULL;
const char *comp = dp->d_name.name;
- struct dentry *res = NULL;
struct inode *ip = NULL;
int code;
@@ -894,24 +895,33 @@
code = afs_lookup(VTOAFS(dip), comp, &vcp, credp);
if (vcp) {
- ip = AFSTOV(vcp);
+ struct vattr vattr;
+ ip = AFSTOV(vcp);
afs_getattr(vcp, &vattr, credp);
afs_fill_inode(ip, &vattr);
}
dp->d_op = &afs_dentry_operations;
dp->d_time = hgetlo(VTOAFS(dip)->m.DataVersion);
AFS_GUNLOCK();
+
#if defined(AFS_LINUX24_ENV)
if (ip && S_ISDIR(ip->i_mode)) {
- d_prune_aliases(ip);
- res = d_find_alias(ip);
+ struct dentry *alias;
+
+ alias = d_find_alias(ip);
+ if (alias) {
+ if (d_invalidate(alias) == 0) {
+ dput(alias);
+ } else {
+ iput(ip);
+#if defined(AFS_LINUX26_ENV)
+ unlock_kernel();
+#endif
+ return alias;
+ }
+ }
}
- if (res) {
- if (d_unhashed(res))
- d_rehash(res);
- iput(ip);
- } else
#endif
d_add(dp, ip);
@@ -923,10 +933,6 @@
/* It's ok for the file to not be found. That's noted by the caller by
* seeing that the dp->d_inode field is NULL.
*/
-#if defined(AFS_LINUX24_ENV)
- if (code == 0)
- return res;
-#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
if (code == ENOENT)
return ERR_PTR(0);