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 <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
This commit is contained in:
Andrew Deason 2018-07-08 15:00:02 -05:00 committed by Benjamin Kaduk
parent 6c808e05ad
commit ba8b92401b

View File

@ -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);