diff options
author | Ingo Molnar <mingo@elte.hu> | 2005-01-07 21:50:46 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-01-07 21:50:46 -0800 |
commit | 116194f29f13541a261b0523f710b2723bd62b9f (patch) | |
tree | e93018ceb83b8f836c662a8aa0fc6a7b77ecef6c /fs | |
parent | 8f254b62810cb1333e24bbabd3cd64637ea5f5d3 (diff) | |
download | history-116194f29f13541a261b0523f710b2723bd62b9f.tar.gz |
[PATCH] sched: vfs: fix scheduling latencies in prune_dcache() and select_parent()
The attached patch fixes long scheduling latencies in select_parent() and
prune_dcache(). The prune_dcache() lock-break is easy, but for
select_parent() the only viable solution i found was to break out if
there's a resched necessary - the reordering is not necessary and the
dcache scanning/shrinking will later on do it anyway.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/dcache.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index bd8f593a3a7dc8..9d457dfc3d676b 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -156,7 +156,7 @@ repeat: spin_unlock(&dcache_lock); return; } - + /* * AV: ->d_delete() is _NOT_ allowed to block now. */ @@ -392,6 +392,8 @@ static void prune_dcache(int count) struct dentry *dentry; struct list_head *tmp; + cond_resched_lock(&dcache_lock); + tmp = dentry_unused.prev; if (tmp == &dentry_unused) break; @@ -548,6 +550,13 @@ positive: * list for prune_dcache(). We descend to the next level * whenever the d_subdirs list is non-empty and continue * searching. + * + * It returns zero iff there are no unused children, + * otherwise it returns the number of children moved to + * the end of the unused list. This may not be the total + * number of unused children, because select_parent can + * drop the lock and return early due to latency + * constraints. */ static int select_parent(struct dentry * parent) { @@ -577,6 +586,15 @@ resume: dentry_stat.nr_unused++; found++; } + + /* + * We can return to the caller if we have found some (this + * ensures forward progress). We'll be coming back to find + * the rest. + */ + if (found && need_resched()) + goto out; + /* * Descend a level if the d_subdirs list is non-empty. */ @@ -601,6 +619,7 @@ this_parent->d_parent->d_name.name, this_parent->d_name.name, found); #endif goto resume; } +out: spin_unlock(&dcache_lock); return found; } |