disconnected-dirty-list-keeps-reference-to-vcache-20081130
authorDragos Tatulea <dragos.tatulea@gmail.com>
Sun, 30 Nov 2008 20:06:35 +0000 (20:06 +0000)
committerDerrick Brashear <shadow@dementia.org>
Sun, 30 Nov 2008 20:06:35 +0000 (20:06 +0000)
LICENSE IPL10
FIXES 123715

avoid putting vcaches on the dirty list unreferenced

src/afs/LINUX/osi_vnodeops.c
src/afs/VNOPS/afs_vnop_create.c
src/afs/VNOPS/afs_vnop_dirops.c
src/afs/VNOPS/afs_vnop_remove.c
src/afs/VNOPS/afs_vnop_rename.c
src/afs/VNOPS/afs_vnop_write.c
src/afs/afs_dcache.c
src/afs/afs_disconnected.c
src/afs/afs_vcache.c
src/afs/discon.h
src/afs/lock.h

index b3985e3..70f7098 100644 (file)
@@ -667,7 +667,7 @@ afs_linux_flush(struct file *fp)
                    (vcp->ddirty_flags == VDisconShadowed)) {
 
                    ObtainWriteLock(&afs_DDirtyVCListLock, 710);
-                   AFS_DISCON_ADD_DIRTY(vcp);
+                   AFS_DISCON_ADD_DIRTY(vcp, 1);
                    ReleaseWriteLock(&afs_DDirtyVCListLock);
                }
 
index 2127a9b..1f97465 100644 (file)
@@ -465,8 +465,8 @@ afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
                if (!tvc->ddirty_flags ||
                        (tvc->ddirty_flags == VDisconShadowed)) {
                    /* Put it in the list only if it's fresh. */
-                   ObtainWriteLock(&afs_DDirtyVCListLock, 729);
-                   AFS_DISCON_ADD_DIRTY(tvc);
+                   ObtainWriteLock(&afs_DDirtyVCListLock, 729);
+                   AFS_DISCON_ADD_DIRTY(tvc, 0);
                    ReleaseWriteLock(&afs_DDirtyVCListLock);
                }
 
index f6f7ded..704c168 100644 (file)
@@ -229,7 +229,7 @@ afs_mkdir(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
 
            /* Put it in the list only if it's fresh. */
            ObtainWriteLock(&afs_DDirtyVCListLock, 730);
-           AFS_DISCON_ADD_DIRTY(tvc);
+           AFS_DISCON_ADD_DIRTY(tvc, 1);
            ReleaseWriteLock(&afs_DDirtyVCListLock);
        }
 
@@ -438,7 +438,7 @@ afs_rmdir(OSI_VC_DECL(adp), char *aname, struct AFS_UCRED *acred)
        if (!tvc->ddirty_flags) {
            /* Put it in the list only if it's fresh or has only been shadowed. */
            ObtainWriteLock(&afs_DDirtyVCListLock, 728);
-           AFS_DISCON_ADD_DIRTY(tvc);
+           AFS_DISCON_ADD_DIRTY(tvc, 1);
            ReleaseWriteLock(&afs_DDirtyVCListLock);
        }
 
@@ -476,9 +476,7 @@ afs_rmdir(OSI_VC_DECL(adp), char *aname, struct AFS_UCRED *acred)
        ObtainWriteLock(&tvc->lock, 155);
        tvc->states &= ~CUnique;        /* For the dfs xlator */
        ReleaseWriteLock(&tvc->lock);
-       /* If disconnected, keep this vcache around for resync. */
-       if (!AFS_IS_DISCON_RW)
-           afs_PutVCache(tvc);
+       afs_PutVCache(tvc);
     }
     ReleaseWriteLock(&adp->lock);
     /* don't worry about link count since dirs can not be hardlinked */
index 36cdf7b..33b4b5e 100644 (file)
@@ -184,11 +184,7 @@ afsremove(register struct vcache *adp, register struct dcache *tdc,
 #ifdef AFS_BOZONLOCK_ENV
        afs_BozonUnlock(&tvc->pvnLock, tvc);
 #endif
-       /* Don't decrease refcount for this vcache if disconnected, we will
-        * need it during replay.
-        */
-       if (!AFS_IS_DISCON_RW)
-           afs_PutVCache(tvc);
+       afs_PutVCache(tvc);
     }
     return (0);
 }
@@ -374,7 +370,7 @@ afs_remove(OSI_VC_DECL(adp), char *aname, struct AFS_UCRED *acred)
                (tvc->ddirty_flags == VDisconShadowed)) {
            /* Add to list only if fresh. */
            ObtainWriteLock(&afs_DDirtyVCListLock, 725);
-           AFS_DISCON_ADD_DIRTY(tvc);
+           AFS_DISCON_ADD_DIRTY(tvc, 1);
            ReleaseWriteLock(&afs_DDirtyVCListLock);
        }
 
index 647d744..cb7a3f0 100644 (file)
@@ -230,8 +230,8 @@ afsrename(struct vcache *aodp, char *aname1, struct vcache *andp,
                        (tvc->ddirty_flags == VDisconShadowed)) {
                    /* Add in dirty list.*/
                    ObtainWriteLock(&afs_DDirtyVCListLock, 751);
-                   AFS_DISCON_ADD_DIRTY(tvc);
-                   ReleaseWriteLock(&afs_DDirtyVCListLock);
+                   AFS_DISCON_ADD_DIRTY(tvc, 1);
+                   ReleaseWriteLock(&afs_DDirtyVCListLock);
                }
 
                ObtainWriteLock(&tvc->lock, 750);
index 6a1f9b5..28cbf19 100644 (file)
@@ -91,9 +91,10 @@ afs_StoreOnLastReference(register struct vcache *avc,
 
        if (!avc->ddirty_flags ||
                (avc->ddirty_flags == VDisconShadowed)) {
+
            /* Add to disconnected dirty list. */
-           AFS_DISCON_ADD_DIRTY(avc);
-       }
+           AFS_DISCON_ADD_DIRTY(avc, 1);
+       }
 
        /* Set disconnected write flag. */
        avc->ddirty_flags |= VDisconWriteClose;
@@ -1090,7 +1091,7 @@ afs_fsync(OSI_VC_DECL(avc), struct AFS_UCRED *acred)
                (avc->ddirty_flags == VDisconShadowed)) {
 
                /* Add to disconnected dirty list. */
-               AFS_DISCON_ADD_DIRTY(avc);
+               AFS_DISCON_ADD_DIRTY(avc, 1);
            }
 
            UpgradeSToWLock(&avc->lock, 711);
index f8ccc06..68cf6f7 100644 (file)
@@ -3810,7 +3810,7 @@ done:
     if (!ret_code) {
        if (!avc->ddirty_flags) {
            ObtainWriteLock(&afs_DDirtyVCListLock, 763);
-           AFS_DISCON_ADD_DIRTY(avc);
+           AFS_DISCON_ADD_DIRTY(avc, 1);
            ReleaseWriteLock(&afs_DDirtyVCListLock);
        }
        avc->shVnode = shadow_fid.Fid.Vnode;
index 4d5f192..aeeaaa3 100644 (file)
@@ -1283,11 +1283,10 @@ skip_file:
                    /* We can discard the shadow dir now. */
                    afs_DeleteShadowDir(tmp);
 
-               if (tmp->ddirty_flags & VDisconRemove)
-                   /* Drop the refcount on the deleted vnodes,
-                    * because we don't need them anymore.
-                    */
-                   afs_PutVCache(tmp);
+               /* Drop the refcount on this vnode because it's not in the
+                * list anymore.
+                */
+                afs_PutVCache(tmp);
 
                /* Only if sync was successfull,
                 * clear flags and dirty references.
index 3307e51..3f76f69 100644 (file)
@@ -1624,7 +1624,7 @@ int afs_WriteVCacheDiscon(register struct vcache *avc,
        if (!avc->ddirty_flags ||
                (avc->ddirty_flags == VDisconShadowed)) {
                /* Not in dirty list. */
-               AFS_DISCON_ADD_DIRTY(avc);
+               AFS_DISCON_ADD_DIRTY(avc, 1);
        }
 
        avc->ddirty_flags |= flags;
index 2ad358e..ef95e27 100644 (file)
@@ -9,7 +9,7 @@
 #define AFS_DISCON_LOCK()
 #define AFS_DISCON_UNLOCK()
 
-#define AFS_DISCON_ADD_DIRTY(avc)
+#define AFS_DISCON_ADD_DIRTY(avc, lock)
 
 #else
 
@@ -66,14 +66,21 @@ extern void afs_RemoveAllConns();
 #define AFS_DISCON_LOCK() ObtainReadLock(&afs_discon_lock)
 #define AFS_DISCON_UNLOCK() ReleaseReadLock(&afs_discon_lock)
 
-#define AFS_DISCON_ADD_DIRTY(avc)                              \
+/* Call with avc and afs_DDirtyVCListLock w locks held. */
+#define AFS_DISCON_ADD_DIRTY(avc, lock)                                \
 do {                                                           \
+    int retry = 0;                                             \
     if (!afs_DDirtyVCListStart) {                              \
        afs_DDirtyVCListStart = afs_DDirtyVCList = avc;         \
     } else {                                                   \
        afs_DDirtyVCList->ddirty_next = avc;                    \
        afs_DDirtyVCList = avc;                                 \
     }                                                          \
+    if (lock)                                                  \
+       ObtainWriteLock(&afs_xvcache, 763);                     \
+    osi_vnhold(avc, 0);                                                \
+    if (lock)                                                  \
+       ReleaseWriteLock(&afs_xvcache);                         \
 } while(0);
 
 #endif /* AFS_DISCON_ENV */
index 27787a0..7578956 100644 (file)
@@ -31,7 +31,7 @@
 /* This is the max lock number in use. Please update it if you add any new
  * lock numbers.
  */
-#define MAX_LOCK_NUMBER 760
+#define MAX_LOCK_NUMBER 780
 #endif
 
 struct afs_bozoLock {