aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-09-21 20:47:20 -0400
committerAlex Elder <aelder@sgi.com>2010-10-18 16:07:44 -0400
commite176579e70118ed7cfdb60f963628fe0ca771f3d (patch)
treee2d252fcd692aa4e3907300521e2af81c974f875 /fs/xfs/linux-2.6
parentbd32d25a7cf7242512e77e70bab63df4402ab91c (diff)
xfs: lockless per-ag lookups
When we start taking a reference to the per-ag for every cached buffer in the system, kernel lockstat profiling on an 8-way create workload shows the mp->m_perag_lock has higher acquisition rates than the inode lock and has significantly more contention. That is, it becomes the highest contended lock in the system. The perag lookup is trivial to convert to lock-less RCU lookups because perag structures never go away. Hence the only thing we need to protect against is tree structure changes during a grow. This can be done simply by replacing the locking in xfs_perag_get() with RCU read locking. This removes the mp->m_perag_lock completely from this path. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 81976ffed7d6..3a1d229b4784 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -150,17 +150,17 @@ xfs_inode_ag_iter_next_pag(
150 int found; 150 int found;
151 int ref; 151 int ref;
152 152
153 spin_lock(&mp->m_perag_lock); 153 rcu_read_lock();
154 found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, 154 found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
155 (void **)&pag, *first, 1, tag); 155 (void **)&pag, *first, 1, tag);
156 if (found <= 0) { 156 if (found <= 0) {
157 spin_unlock(&mp->m_perag_lock); 157 rcu_read_unlock();
158 return NULL; 158 return NULL;
159 } 159 }
160 *first = pag->pag_agno + 1; 160 *first = pag->pag_agno + 1;
161 /* open coded pag reference increment */ 161 /* open coded pag reference increment */
162 ref = atomic_inc_return(&pag->pag_ref); 162 ref = atomic_inc_return(&pag->pag_ref);
163 spin_unlock(&mp->m_perag_lock); 163 rcu_read_unlock();
164 trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_); 164 trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_);
165 } else { 165 } else {
166 pag = xfs_perag_get(mp, *first); 166 pag = xfs_perag_get(mp, *first);