From ba8b92401b8cb2f5a5306313c2702cb36cba083c Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Sun, 8 Jul 2018 15:00:02 -0500 Subject: [PATCH 1/1] afs: Bound afs_DoBulkStat dir scan Currently, afs_DoBulkStat will scan the entire directory blob, looking for entries to stat. If all or almost all entries are already stat'd, we'll scan through the entire directory, doing nontrivial work on each entry (we grab afs_xvcache, at least). All of this work is pretty pointless, since the entries are already cached and so we won't do anything. If many processes are trying to acquire afs_xvcache, this can contribute to performance issues. To avoid this, provide a constant bound on the number of entries we'll search through: nentries * 4. The current arbitrary limits cap nentries at 30, so this means we're capping the afs_DoBulkStat search to 120 entries. Change-Id: I66e9af5b27844ddf6cf37c8286fcc65f8e0d3f96 Reviewed-on: https://gerrit.openafs.org/13253 Tested-by: BuildBot Reviewed-by: Benjamin Kaduk --- src/afs/VNOPS/afs_vnop_lookup.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 2f26b70..8534707 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -691,6 +691,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) struct VenusFid dotdot = {0, {0, 0, 0}}; int flagIndex = 0; /* First file with bulk fetch flag set */ struct rx_connection *rxconn; + int attempt_i; XSTATS_DECLS; dotdot.Cell = 0; dotdot.Fid.Unique = 0; @@ -784,7 +785,18 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) /* now we have dir data in the cache, so scan the dir page */ fidIndex = 0; flagIndex = 0; - while (1) { /* Should probably have some constant bound */ + + /* + * Only examine at most the next 'nentries*4' entries to find dir entries + * to stat. This is an arbitrary limit that we set so we don't waste time + * scanning an entire dir that contains stat'd entries. For example, if a + * dir contains 10k entries, and all or almost all of them are stat'd, then + * we'll examine 10k entries for no benefit. For each entry, we run + * afs_FindVCache, and grab and release afs_xvcache; doing this e.g. 10k + * times can have significant impact if the client is under a lot of load. + */ + for (attempt_i = 0; attempt_i < nentries * 4; attempt_i++) { + /* look for first safe entry to examine in the directory. BlobScan * looks for a the 1st allocated dir after the dirCookie slot. */ @@ -920,7 +932,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) if (temp <= 0) break; dirCookie += temp; - } /* while loop over all dir entries */ + } /* for loop over dir entries */ /* now release the dir lock and prepare to make the bulk RPC */ ReleaseReadLock(&dcp->lock); -- 1.9.4