From 2bce3b50ef4fd9b9bdd03daf6e8332710f541922 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Thu, 4 Aug 2011 17:08:45 -0400 Subject: [PATCH] Windows: after dir enum adjust dir scache LRU During a directory enumeration the directory scache object is reference counted so it can't be recycled. However, if there are more directory entries than the maximum number of cached scache objects the directory scache object will end up being the next object to be recycled after the refcount is dropped. Since the directory is clearly a hot object, before dropping the reference, adjust the scache LRU position so that it is the last object to be recycled. Fix the variable name for the directory scache to be 'dscp' for consistency. Change-Id: Ia2089fb9b47dab77abc0911ab009e5aed75ed848 Reviewed-on: http://gerrit.openafs.org/5158 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/cm_btree.c | 41 ++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/WINNT/afsd/cm_btree.c b/src/WINNT/afsd/cm_btree.c index c916fb50e..212ef4185 100644 --- a/src/WINNT/afsd/cm_btree.c +++ b/src/WINNT/afsd/cm_btree.c @@ -2175,7 +2175,7 @@ cm_BPlusEnumAlloc(afs_uint32 entries) } long -cm_BPlusDirEnumerate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, +cm_BPlusDirEnumerate(cm_scache_t *dscp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked, clientchar_t * maskp, afs_uint32 fetchStatus, cm_direnum_t **enumpp) { @@ -2190,23 +2190,23 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, /* Read lock the bplus tree so the data can't change */ if (!locked) - lock_ObtainRead(&scp->dirlock); + lock_ObtainRead(&dscp->dirlock); /* - * Hold a reference to the directory so that it wont' be + * Hold a reference to the directory so that it won't be * recycled while the enumeration is active. */ - cm_HoldSCache(scp); + cm_HoldSCache(dscp); cm_HoldUser(userp); - if (scp->dirBplus == NULL) { + if (dscp->dirBplus == NULL) { osi_Log0(afsd_logp, "cm_BPlusDirEnumerate No BPlus Tree"); rc = CM_ERROR_WOULDBLOCK; goto done; } /* Compute the number of entries */ - for (count = 0, leafNode = getleaf(scp->dirBplus); leafNode; leafNode = nextLeafNode) { + for (count = 0, leafNode = getleaf(dscp->dirBplus); leafNode; leafNode = nextLeafNode) { for ( slot = 1, numentries = numentries(leafNode); slot <= numentries; slot++) { firstDataNode = getnode(leafNode, slot); @@ -2244,7 +2244,7 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, } /* Copy the name and fid for each cname entry into the enumeration */ - for (count = 0, leafNode = getleaf(scp->dirBplus); leafNode; leafNode = nextLeafNode) { + for (count = 0, leafNode = getleaf(dscp->dirBplus); leafNode; leafNode = nextLeafNode) { for ( slot = 1, numentries = numentries(leafNode); slot <= numentries; slot++) { firstDataNode = getnode(leafNode, slot); @@ -2298,21 +2298,28 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, nextLeafNode = getnextnode(leafNode); } - enump->dscp = scp; + enump->dscp = dscp; enump->userp = userp; enump->reqFlags = reqp->flags; enump->fetchStatus = fetchStatus; done: if (!locked) - lock_ReleaseRead(&scp->dirlock); + lock_ReleaseRead(&dscp->dirlock); /* if we failed, cleanup any mess */ if (rc != 0) { osi_Log0(afsd_logp, "cm_BPlusDirEnumerate rc != 0"); - /* release the directory because we failed to generate an enumeration object */ - cm_ReleaseSCache(scp); + /* + * release the directory because we failed to generate an enumeration object. + * adjust the directory position in the queue to ensure it doesn't get pushed + * out by the allocation of a large number of cm_scache objects. + */ + lock_ObtainWrite(&cm_scacheLock); + cm_AdjustScacheLRU(dscp); + cm_ReleaseSCacheNoLock(dscp); + lock_ReleaseWrite(&cm_scacheLock); cm_ReleaseUser(userp); if (enump) { for ( count = 0; count < enump->count && enump->entry[count].name; count++ ) { @@ -2510,8 +2517,16 @@ cm_BPlusDirFreeEnumeration(cm_direnum_t *enump) osi_Log0(afsd_logp, "cm_BPlusDirFreeEnumeration"); if (enump) { - /* Release the directory object */ - cm_ReleaseSCache(enump->dscp); + /* + * Release the directory object but first adjust its position + * in the LRU queue to ensure that it does not get stuck at the + * end due to the allocation of a large number of cm_scache + * entries in the directory. + */ + lock_ObtainWrite(&cm_scacheLock); + cm_AdjustScacheLRU(enump->dscp); + cm_ReleaseSCacheNoLock(enump->dscp); + lock_ReleaseWrite(&cm_scacheLock); cm_ReleaseUser(enump->userp); for ( count = 0; count < enump->count && enump->entry[count].name; count++ ) { -- 2.39.5