From b631ff9b93737d0452b024421c236379fc92b8c8 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. Reviewed-on: http://gerrit.openafs.org/5158 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman (cherry picked from commit 2bce3b50ef4fd9b9bdd03daf6e8332710f541922) Change-Id: Ie4400d769a7ac2d0bfed3ccebe02760619bb76b2 Reviewed-on: http://gerrit.openafs.org/5208 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- 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 314c9253a..542a9a1da 100644 --- a/src/WINNT/afsd/cm_btree.c +++ b/src/WINNT/afsd/cm_btree.c @@ -2171,7 +2171,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) { @@ -2186,23 +2186,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); @@ -2240,7 +2240,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); @@ -2294,21 +2294,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++ ) { @@ -2506,8 +2513,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