Reduction global superblock lock contention near ENOSPC.
The existing per-cpu superblock counter code uses the global
superblock spin lock when we approach ENOSPC for global
synchronisation. On larger machines than this code was originally
tested on this can still get catastrophic spinlock contention due
increasing rebalance frequency near ENOSPC.
By introducing a sleeping lock that is used to serialise balances
and modifications near ENOSPC we prevent contention from needlessly
from wasting the CPU time of potentially hundreds of CPUs.
To reduce the number of balances occuring, we separate the need
rebalance case from the slow allocate case. Now, a counter
running dry will trigger a rebalance during which counters are
disabled. Any thread that sees a disabled counter enters a different
path where it waits on the new mutex. When it gets the new mutex, it
checks if the counter is disabled. If the counter is disabled, then
we _know_ that we have to use the global counter and lock and it is
safe to do so immediately. Otherwise, we drop the mutex and go back
to trying the per-cpu counters which we know were re-enabled.
Date: Mon Dec 4 11:24:40 AEDT 2006
Inspected by: lachlan
The following file(s) were checked into:
fs/xfs/xfs_mount.h - 1.228 - changed
- Add a new per-cpu counter synchronisation mutex.
fs/xfs/xfs_mount.c - 1.388 - changed
- Reduce contention on the XFS_SB_LOCK() near ENOSPC by introducing
a sleeping mutex for per-cpu superblock counter synchronisation
and reworking the slow path to reduce counter rebalance frequency.