[OpenAFS-devel] Re: understanding afs_remunlink() and why .__afsXXX don't get cleaned up (FIXED!)

chas williams - CONTRACTOR chas@cmf.nrl.navy.mil
Thu, 01 Mar 2007 14:43:51 -0500


In message <45E725ED.7030800@mikefedyk.com>,Mike Fedyk writes:
>> could you try this version.  it adds a vnode_recycle()/cache_purge() 
>> to the afs_vop_inactive() if it stumbles across an unlinked file.
>> 
>> also, it adds a vnode_recycle() for successful rmdir's and doesnt 
>> do cache_purges() when remove operations fail.
>
>I imagine that afs_vop_inactive() somewhere in the directory listing 
>code.  If so can you print out a warning in the logs?
>
>It's good to clean up after a spill, but at least we'll know that there 
>has been a spill this way.

its not really a spill, its just that afs does its unlink of busy files
differently.  its similar to nfs, so after looking at the nfs yesterday
code i spotted this helpful comment in nfs remove stub:

	/* clear flags now: won't get nfs_inactive for recycled vnode */

so nfs skips the vnode_recycle() and does it cleanup in the inactive
stub.  the following seems like a good approximation.

Index: src/afs/DARWIN/osi_vnodeops.c
===================================================================
--- src/afs/DARWIN/osi_vnodeops.c	(revision 78)
+++ src/afs/DARWIN/osi_vnodeops.c	(revision 79)
@@ -1192,8 +1192,12 @@
     cache_purge(vp);
     if (!error) {
 #ifdef AFS_DARWIN80_ENV
-        ubc_setsize(vp, (off_t)0);
-        vnode_recycle(vp);
+	struct vcache *tvc = VTOAFS(vp);
+
+	if (!(tvc->states & CUnlinked)) {
+            ubc_setsize(vp, (off_t)0);
+            vnode_recycle(vp);
+	}
 #else
         /* necessary so we don't deadlock ourselves in vclean */
         VOP_UNLOCK(vp, 0, cnp->cn_proc);
@@ -1619,14 +1623,24 @@
 {
     register struct vnode *vp = ap->a_vp;
     struct vcache *tvc = VTOAFS(vp);
+
 #ifndef AFS_DARWIN80_ENV
     if (prtactive && vp->v_usecount != 0)
 	vprint("afs_vop_inactive(): pushing active", vp);
 #endif
     if (tvc) {
-       AFS_GLOCK();
-       afs_InactiveVCache(tvc, 0);	/* decrs ref counts */
-       AFS_GUNLOCK();
+#ifdef AFS_DARWIN80_ENV
+        int unlinked = tvc->states & CUnlinked;
+#endif
+	AFS_GLOCK();
+	afs_InactiveVCache(tvc, 0);	/* decrs ref counts */
+	AFS_GUNLOCK();
+#ifdef AFS_DARWIN80_ENV
+	if (unlinked) {
+	    vnode_recycle(vp);
+	    cache_purge(vp);
+	}
+#endif
     }
 #ifndef AFS_DARWIN80_ENV
     VOP_UNLOCK(vp, 0, ap->a_p);