aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-04-24 15:06:17 -0400
committerAlex Elder <aelder@sgi.com>2011-04-28 14:18:09 -0400
commit8a072a4d4c6a5b6ec32836c467d2996393c76c6f (patch)
treeb21dad1310e4351854b9e2e24feb86beed20d1f7 /fs
parent97d3ac75e5e0ebf7ca38ae74cebd201c09b97ab2 (diff)
xfs: reduce the number of pagb_lock roundtrips in xfs_alloc_clear_busy
Instead of finding the per-ag and then taking and releasing the pagb_lock for every single busy extent completed sort the list of busy extents and only switch betweens AGs where nessecary. This becomes especially important with the online discard support which will hit this lock more often. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h1
-rw-r--r--fs/xfs/xfs_alloc.c56
-rw-r--r--fs/xfs/xfs_alloc.h11
-rw-r--r--fs/xfs/xfs_log_cil.c5
-rw-r--r--fs/xfs/xfs_trans.c6
6 files changed, 61 insertions, 19 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 9ef9ed2cfe2e..098890357659 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -33,7 +33,6 @@
33#include <linux/migrate.h> 33#include <linux/migrate.h>
34#include <linux/backing-dev.h> 34#include <linux/backing-dev.h>
35#include <linux/freezer.h> 35#include <linux/freezer.h>
36#include <linux/list_sort.h>
37 36
38#include "xfs_sb.h" 37#include "xfs_sb.h"
39#include "xfs_inum.h" 38#include "xfs_inum.h"
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 244be9cbfe78..8633521b3b2e 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -70,6 +70,7 @@
70#include <linux/ctype.h> 70#include <linux/ctype.h>
71#include <linux/writeback.h> 71#include <linux/writeback.h>
72#include <linux/capability.h> 72#include <linux/capability.h>
73#include <linux/list_sort.h>
73 74
74#include <asm/page.h> 75#include <asm/page.h>
75#include <asm/div64.h> 76#include <asm/div64.h>
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 53157d4d5e8b..44a51a7b4c3a 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2964,24 +2964,60 @@ fail:
2964 *rlen = 0; 2964 *rlen = 0;
2965} 2965}
2966 2966
2967void 2967static void
2968xfs_alloc_busy_clear( 2968xfs_alloc_busy_clear_one(
2969 struct xfs_mount *mp, 2969 struct xfs_mount *mp,
2970 struct xfs_perag *pag,
2970 struct xfs_busy_extent *busyp) 2971 struct xfs_busy_extent *busyp)
2971{ 2972{
2972 struct xfs_perag *pag;
2973
2974 list_del_init(&busyp->list);
2975
2976 pag = xfs_perag_get(mp, busyp->agno);
2977 spin_lock(&pag->pagb_lock);
2978 if (busyp->length) { 2973 if (busyp->length) {
2979 trace_xfs_alloc_busy_clear(mp, busyp->agno, busyp->bno, 2974 trace_xfs_alloc_busy_clear(mp, busyp->agno, busyp->bno,
2980 busyp->length); 2975 busyp->length);
2981 rb_erase(&busyp->rb_node, &pag->pagb_tree); 2976 rb_erase(&busyp->rb_node, &pag->pagb_tree);
2982 } 2977 }
2983 spin_unlock(&pag->pagb_lock);
2984 xfs_perag_put(pag);
2985 2978
2979 list_del_init(&busyp->list);
2986 kmem_free(busyp); 2980 kmem_free(busyp);
2987} 2981}
2982
2983void
2984xfs_alloc_busy_clear(
2985 struct xfs_mount *mp,
2986 struct list_head *list)
2987{
2988 struct xfs_busy_extent *busyp, *n;
2989 struct xfs_perag *pag = NULL;
2990 xfs_agnumber_t agno = NULLAGNUMBER;
2991
2992 list_for_each_entry_safe(busyp, n, list, list) {
2993 if (busyp->agno != agno) {
2994 if (pag) {
2995 spin_unlock(&pag->pagb_lock);
2996 xfs_perag_put(pag);
2997 }
2998 pag = xfs_perag_get(mp, busyp->agno);
2999 spin_lock(&pag->pagb_lock);
3000 agno = busyp->agno;
3001 }
3002
3003 xfs_alloc_busy_clear_one(mp, pag, busyp);
3004 }
3005
3006 if (pag) {
3007 spin_unlock(&pag->pagb_lock);
3008 xfs_perag_put(pag);
3009 }
3010}
3011
3012/*
3013 * Callback for list_sort to sort busy extents by the AG they reside in.
3014 */
3015int
3016xfs_busy_extent_ag_cmp(
3017 void *priv,
3018 struct list_head *a,
3019 struct list_head *b)
3020{
3021 return container_of(a, struct xfs_busy_extent, list)->agno -
3022 container_of(b, struct xfs_busy_extent, list)->agno;
3023}
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index de5e27c95170..240ad288f2f9 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -140,7 +140,7 @@ xfs_alloc_busy_insert(struct xfs_trans *tp, xfs_agnumber_t agno,
140 xfs_agblock_t bno, xfs_extlen_t len); 140 xfs_agblock_t bno, xfs_extlen_t len);
141 141
142void 142void
143xfs_alloc_busy_clear(struct xfs_mount *mp, struct xfs_busy_extent *busyp); 143xfs_alloc_busy_clear(struct xfs_mount *mp, struct list_head *list);
144 144
145int 145int
146xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno, 146xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno,
@@ -149,6 +149,15 @@ xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno,
149void 149void
150xfs_alloc_busy_reuse(struct xfs_mount *mp, xfs_agnumber_t agno, 150xfs_alloc_busy_reuse(struct xfs_mount *mp, xfs_agnumber_t agno,
151 xfs_agblock_t fbno, xfs_extlen_t flen, bool userdata); 151 xfs_agblock_t fbno, xfs_extlen_t flen, bool userdata);
152
153int
154xfs_busy_extent_ag_cmp(void *priv, struct list_head *a, struct list_head *b);
155
156static inline void xfs_alloc_busy_sort(struct list_head *list)
157{
158 list_sort(NULL, list, xfs_busy_extent_ag_cmp);
159}
160
152#endif /* __KERNEL__ */ 161#endif /* __KERNEL__ */
153 162
154/* 163/*
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 9ca59be08977..7d56e88a3f0e 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -361,13 +361,12 @@ xlog_cil_committed(
361 int abort) 361 int abort)
362{ 362{
363 struct xfs_cil_ctx *ctx = args; 363 struct xfs_cil_ctx *ctx = args;
364 struct xfs_busy_extent *busyp, *n;
365 364
366 xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain, 365 xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain,
367 ctx->start_lsn, abort); 366 ctx->start_lsn, abort);
368 367
369 list_for_each_entry_safe(busyp, n, &ctx->busy_extents, list) 368 xfs_alloc_busy_sort(&ctx->busy_extents);
370 xfs_alloc_busy_clear(ctx->cil->xc_log->l_mp, busyp); 369 xfs_alloc_busy_clear(ctx->cil->xc_log->l_mp, &ctx->busy_extents);
371 370
372 spin_lock(&ctx->cil->xc_cil_lock); 371 spin_lock(&ctx->cil->xc_cil_lock);
373 list_del(&ctx->committing); 372 list_del(&ctx->committing);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 76922793f64f..d1f24858ccc4 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -608,10 +608,8 @@ STATIC void
608xfs_trans_free( 608xfs_trans_free(
609 struct xfs_trans *tp) 609 struct xfs_trans *tp)
610{ 610{
611 struct xfs_busy_extent *busyp, *n; 611 xfs_alloc_busy_sort(&tp->t_busy);
612 612 xfs_alloc_busy_clear(tp->t_mountp, &tp->t_busy);
613 list_for_each_entry_safe(busyp, n, &tp->t_busy, list)
614 xfs_alloc_busy_clear(tp->t_mountp, busyp);
615 613
616 atomic_dec(&tp->t_mountp->m_active_trans); 614 atomic_dec(&tp->t_mountp->m_active_trans);
617 xfs_trans_free_dqinfo(tp); 615 xfs_trans_free_dqinfo(tp);