Commit 116194f2 authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds

[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: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarNick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 8f254b62
...@@ -156,7 +156,7 @@ void dput(struct dentry *dentry) ...@@ -156,7 +156,7 @@ void dput(struct dentry *dentry)
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return; return;
} }
/* /*
* AV: ->d_delete() is _NOT_ allowed to block now. * AV: ->d_delete() is _NOT_ allowed to block now.
*/ */
...@@ -392,6 +392,8 @@ static void prune_dcache(int count) ...@@ -392,6 +392,8 @@ static void prune_dcache(int count)
struct dentry *dentry; struct dentry *dentry;
struct list_head *tmp; struct list_head *tmp;
cond_resched_lock(&dcache_lock);
tmp = dentry_unused.prev; tmp = dentry_unused.prev;
if (tmp == &dentry_unused) if (tmp == &dentry_unused)
break; break;
...@@ -548,6 +550,13 @@ int have_submounts(struct dentry *parent) ...@@ -548,6 +550,13 @@ int have_submounts(struct dentry *parent)
* list for prune_dcache(). We descend to the next level * list for prune_dcache(). We descend to the next level
* whenever the d_subdirs list is non-empty and continue * whenever the d_subdirs list is non-empty and continue
* searching. * 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) static int select_parent(struct dentry * parent)
{ {
...@@ -577,6 +586,15 @@ static int select_parent(struct dentry * parent) ...@@ -577,6 +586,15 @@ static int select_parent(struct dentry * parent)
dentry_stat.nr_unused++; dentry_stat.nr_unused++;
found++; 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. * 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); ...@@ -601,6 +619,7 @@ this_parent->d_parent->d_name.name, this_parent->d_name.name, found);
#endif #endif
goto resume; goto resume;
} }
out:
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return found; return found;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment