Messages in this thread Patch in this message | | | From | Jan Kara <> | Subject | [PATCH] vfs: Avoid IPI storm due to bh LRU invalidation | Date | Mon, 6 Feb 2012 14:55:31 +0100 |
| |
When discovery of lots of disks happen in parallel, we call invalidate_bh_lrus() once for each disk from partitioning code resulting in a storm of IPIs and causing a softlockup detection to fire (it takes several *minutes* for a machine to execute all the invalidate_bh_lrus() calls).
Fix the issue by allowing only single invalidation to run using a mutex and let waiters for mutex figure out whether someone invalidated LRUs for them while they were waiting.
Signed-off-by: Jan Kara <jack@suse.cz> --- fs/buffer.c | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-)
I feel this is slightly hacky approach but it works. If someone has better idea, please speak up.
diff --git a/fs/buffer.c b/fs/buffer.c index 1a30db7..56b0d2b 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1384,10 +1384,31 @@ static void invalidate_bh_lru(void *arg) } put_cpu_var(bh_lrus); } - + +/* + * Invalidate all buffers in LRUs. Since we have to signal all CPUs to + * invalidate their per-cpu local LRU lists this is rather expensive operation. + * So we optimize the case of several parallel calls to invalidate_bh_lrus() + * which happens from partitioning code when lots of disks appear in the + * system during boot. + */ void invalidate_bh_lrus(void) { + static DEFINE_MUTEX(bh_invalidate_mutex); + static long bh_invalidate_sequence; + + long my_bh_invalidate_sequence = bh_invalidate_sequence; + + mutex_lock(&bh_invalidate_mutex); + /* Someone did bh invalidation while we were sleeping? */ + if (my_bh_invalidate_sequence != bh_invalidate_sequence) + goto out; + bh_invalidate_sequence++; + /* Inc of bh_invalidate_sequence must happen before we invalidate bhs */ + smp_wmb(); on_each_cpu(invalidate_bh_lru, NULL, 1); +out: + mutex_unlock(&bh_invalidate_mutex); } EXPORT_SYMBOL_GPL(invalidate_bh_lrus); -- 1.7.1
| |