fix quadratic behavior of shrink_dcache_parent()
authorMiklos Szeredi <[email protected]>
Tue, 8 May 2007 07:23:46 +0000 (00:23 -0700)
committerLinus Torvalds <[email protected]>
Tue, 8 May 2007 18:14:58 +0000 (11:14 -0700)
commitd52b908646b88cb1952ab8c9b2d4423908a23f11
tree0c60c3bdbffaf87c7d9cff30e5e598ce31d4789b
parent97dc32cdb1b53832801159d5f634b41aad9d0a23
fix quadratic behavior of shrink_dcache_parent()

The time shrink_dcache_parent() takes, grows quadratically with the depth
of the tree under 'parent'.  This starts to get noticable at about 10,000.

These kinds of depths don't occur normally, and filesystems which invoke
shrink_dcache_parent() via d_invalidate() seem to have other depth
dependent timings, so it's not even easy to expose this problem.

However with FUSE it's easy to create a deep tree and d_invalidate()
will also get called.  This can make a syscall hang for a very long
time.

This is the original discovery of the problem by Russ Cox:

  http://article.gmane.org/gmane.comp.file-systems.fuse.devel/3826

The following patch fixes the quadratic behavior, by optionally allowing
prune_dcache() to prune ancestors of a dentry in one go, instead of doing
it one at a time.

Common code in dput() and prune_one_dentry() is extracted into a new helper
function d_kill().

shrink_dcache_parent() as well as shrink_dcache_sb() are converted to use
the ancestry-pruner option.  Only for shrink_dcache_memory() is this
behavior not desirable, so it keeps using the old algorithm.

Signed-off-by: Miklos Szeredi <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Maneesh Soni <[email protected]>
Acked-by: "Paul E. McKenney" <[email protected]>
Cc: Dipankar Sarma <[email protected]>
Cc: Neil Brown <[email protected]>
Cc: Trond Myklebust <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
fs/dcache.c