From 20aff72a7eae704241b67b6cf40fc92648abb1b0 Mon Sep 17 00:00:00 2001 From: Dragos Tatulea Date: Sun, 30 Nov 2008 20:06:35 +0000 Subject: [PATCH] disconnected-dirty-list-keeps-reference-to-vcache-20081130 LICENSE IPL10 FIXES 123715 avoid putting vcaches on the dirty list unreferenced --- src/afs/LINUX/osi_vnodeops.c | 2 +- src/afs/VNOPS/afs_vnop_create.c | 4 ++-- src/afs/VNOPS/afs_vnop_dirops.c | 8 +++----- src/afs/VNOPS/afs_vnop_remove.c | 8 ++------ src/afs/VNOPS/afs_vnop_rename.c | 4 ++-- src/afs/VNOPS/afs_vnop_write.c | 7 ++++--- src/afs/afs_dcache.c | 2 +- src/afs/afs_disconnected.c | 9 ++++----- src/afs/afs_vcache.c | 2 +- src/afs/discon.h | 11 +++++++++-- src/afs/lock.h | 2 +- 11 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index b3985e3fa..70f709881 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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); } diff --git a/src/afs/VNOPS/afs_vnop_create.c b/src/afs/VNOPS/afs_vnop_create.c index 2127a9bb2..1f974651f 100644 --- a/src/afs/VNOPS/afs_vnop_create.c +++ b/src/afs/VNOPS/afs_vnop_create.c @@ -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); } diff --git a/src/afs/VNOPS/afs_vnop_dirops.c b/src/afs/VNOPS/afs_vnop_dirops.c index f6f7ded86..704c1683b 100644 --- a/src/afs/VNOPS/afs_vnop_dirops.c +++ b/src/afs/VNOPS/afs_vnop_dirops.c @@ -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 */ diff --git a/src/afs/VNOPS/afs_vnop_remove.c b/src/afs/VNOPS/afs_vnop_remove.c index 36cdf7b14..33b4b5e38 100644 --- a/src/afs/VNOPS/afs_vnop_remove.c +++ b/src/afs/VNOPS/afs_vnop_remove.c @@ -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); } diff --git a/src/afs/VNOPS/afs_vnop_rename.c b/src/afs/VNOPS/afs_vnop_rename.c index 647d744d0..cb7a3f0af 100644 --- a/src/afs/VNOPS/afs_vnop_rename.c +++ b/src/afs/VNOPS/afs_vnop_rename.c @@ -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); diff --git a/src/afs/VNOPS/afs_vnop_write.c b/src/afs/VNOPS/afs_vnop_write.c index 6a1f9b52f..28cbf19ba 100644 --- a/src/afs/VNOPS/afs_vnop_write.c +++ b/src/afs/VNOPS/afs_vnop_write.c @@ -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); diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c index f8ccc0688..68cf6f75f 100644 --- a/src/afs/afs_dcache.c +++ b/src/afs/afs_dcache.c @@ -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; diff --git a/src/afs/afs_disconnected.c b/src/afs/afs_disconnected.c index 4d5f19223..aeeaaa37b 100644 --- a/src/afs/afs_disconnected.c +++ b/src/afs/afs_disconnected.c @@ -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. diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 3307e5183..3f76f69ea 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -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; diff --git a/src/afs/discon.h b/src/afs/discon.h index 2ad358ee6..ef95e27d5 100644 --- a/src/afs/discon.h +++ b/src/afs/discon.h @@ -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 */ diff --git a/src/afs/lock.h b/src/afs/lock.h index 27787a00d..7578956fb 100644 --- a/src/afs/lock.h +++ b/src/afs/lock.h @@ -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 { -- 2.39.5