[OpenAFS] IPUT Bad refCount 0 on inode 0xf8abadb8 in openafs-1.2.11

chas williams (contractor) chas@cmf.nrl.navy.mil
Mon, 15 Nov 2004 11:32:51 -0500


In message <20041029140540.GE13909@kalmia.hozed.org>,Troy Benjegerdes writes:
>Trace; f89976c0 <[openafs.mp].rodata.end+4459/d3b9>
>Trace; f8983340 <[openafs.mp]afs_dentry_iput+0/f0>
>Trace; f89a0c44 <[openafs.mp]afs_global_lock+0/1c>
>Trace; f8980168 <[openafs.mp]osi_iput+58/f0>
>Trace; f89976c0 <[openafs.mp].rodata.end+4459/d3b9>
>Trace; f8983340 <[openafs.mp]afs_dentry_iput+0/f0>
>Trace; c015c93b <d_delete+bb/c0>
>Trace; c0153d66 <vfs_unlink+186/280>
>Trace; c0153f1b <sys_unlink+bb/120>
>Trace; c0108efb <system_call+33/38>

can you see if the following attached patch helps this problem.

Index: src/afs/VNOPS/afs_vnop_remove.c
===================================================================
RCS file: /cvs/openafs/src/afs/VNOPS/afs_vnop_remove.c,v
retrieving revision 1.31
diff -u -u -r1.31 afs_vnop_remove.c
--- src/afs/VNOPS/afs_vnop_remove.c	23 Jun 2004 22:25:06 -0000	1.31
+++ src/afs/VNOPS/afs_vnop_remove.c	15 Nov 2004 15:59:50 -0000
@@ -14,9 +14,7 @@
  * afs_IsWired (DUX)
  * afsremove
  * afs_remove
- *
- * Local:
- * newname
+ * afs_newname
  *
  */
 #include <afsconfig.h>
@@ -110,7 +108,7 @@
     register struct conn *tc;
     struct AFSFetchStatus OutDirStatus;
     struct AFSVolSync tsync;
-    XSTATS_DECLS
+    XSTATS_DECLS;
     do {
 	tc = afs_Conn(&adp->fid, treqp, SHARED_LOCK);
 	if (tc) {
@@ -193,8 +191,8 @@
     return (0);
 }
 
-static char *
-newname(void)
+char *
+afs_newname(void)
 {
     char *name, *sp, *p = ".__afs";
     afs_int32 rd = afs_random() & 0xffff;
@@ -412,7 +410,7 @@
 #endif
 #endif
     {
-	char *unlname = newname();
+	char *unlname = afs_newname();
 
 	ReleaseWriteLock(&adp->lock);
 	if (tdc)
Index: src/afs/LINUX/osi_vnodeops.c
===================================================================
RCS file: /cvs/openafs/src/afs/LINUX/osi_vnodeops.c,v
retrieving revision 1.83
diff -u -u -r1.83 osi_vnodeops.c
--- src/afs/LINUX/osi_vnodeops.c	19 Aug 2004 00:58:47 -0000	1.83
+++ src/afs/LINUX/osi_vnodeops.c	15 Nov 2004 15:59:50 -0000
@@ -1149,18 +1149,63 @@
 int
 afs_linux_unlink(struct inode *dip, struct dentry *dp)
 {
-    int code;
+    int code = EBUSY;
     cred_t *credp = crref();
     const char *name = dp->d_name.name;
+    struct vcache *tvc = ITOAFS(dp->d_inode);
 
 #if defined(AFS_LINUX26_ENV)
     lock_kernel();
 #endif
+    if (((VREFCOUNT(tvc) > 0) && tvc->opens > 0)
+				&& !(tvc->states & CUnlinked)) {
+	struct dentry *__dp;
+	char *__name;
+	extern char *afs_newname();
+
+	__dp = NULL;
+	__name = NULL;
+	do {
+	    dput(__dp);
+
+	    AFS_GLOCK();
+	    if (__name)
+		osi_FreeSmallSpace(__name);
+	    __name = afs_newname();
+	    AFS_GUNLOCK();
+
+	    __dp = lookup_one_len(__name, dp->d_parent, strlen(__name));
+		
+	    if (IS_ERR(__dp))
+		goto out;
+	} while (__dp->d_inode != NULL);
+
+	AFS_GLOCK();
+	code = afs_rename(ITOAFS(dip), dp->d_name.name, ITOAFS(dip), __dp->d_name.name, credp);
+	if (!code) {
+            tvc->mvid = __name;
+            crhold(credp);
+            if (tvc->uncred) {
+                crfree(tvc->uncred);
+            }
+            tvc->uncred = credp;
+	    tvc->states |= CUnlinked;
+	}
+	AFS_GUNLOCK();
+
+	if (!code)
+	    d_move(dp, __dp);
+	dput(__dp);
+
+	goto out;
+    }
+
     AFS_GLOCK();
     code = afs_remove(ITOAFS(dip), name, credp);
     AFS_GUNLOCK();
     if (!code)
 	d_drop(dp);
+out:
 #if defined(AFS_LINUX26_ENV)
     unlock_kernel();
 #endif