aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-03-30 11:33:25 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-04-20 03:59:48 -0400
commit29687a2ac8dfcd5363e515ea715ec226aef8c26b (patch)
treea9bb35c110396c9c2a563c9442690cfb3368c8a8 /fs
parent5ac048bb7ea6e87b06504b999017cfa1f38f4092 (diff)
GFS2: Alter point of entry to glock lru list for glocks with an address_space
Rather than allowing the glocks to be scheduled for possible reclaim as soon as they have exited the journal, this patch delays their entry to the list until the glocks in question are no longer in use. This means that we will rely on the vm for writeback of all dirty data and metadata from now on. When glocks are added to the lru list they should be freeable much faster since all the I/O required to free them should have already been completed. This should lead to much better I/O patterns under low memory conditions. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/glock.c33
-rw-r--r--fs/gfs2/glock.h3
-rw-r--r--fs/gfs2/lops.c12
-rw-r--r--fs/gfs2/rgrp.c1
-rw-r--r--fs/gfs2/super.c1
5 files changed, 23 insertions, 27 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index f07643e21bf..1019183232f 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -160,6 +160,19 @@ static int demote_ok(const struct gfs2_glock *gl)
160} 160}
161 161
162 162
163void gfs2_glock_add_to_lru(struct gfs2_glock *gl)
164{
165 spin_lock(&lru_lock);
166
167 if (!list_empty(&gl->gl_lru))
168 list_del_init(&gl->gl_lru);
169 else
170 atomic_inc(&lru_count);
171
172 list_add_tail(&gl->gl_lru, &lru_list);
173 spin_unlock(&lru_lock);
174}
175
163/** 176/**
164 * __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list 177 * __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
165 * @gl: the glock 178 * @gl: the glock
@@ -170,24 +183,8 @@ static int demote_ok(const struct gfs2_glock *gl)
170 183
171static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) 184static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
172{ 185{
173 if (demote_ok(gl)) { 186 if (demote_ok(gl))
174 spin_lock(&lru_lock); 187 gfs2_glock_add_to_lru(gl);
175
176 if (!list_empty(&gl->gl_lru))
177 list_del_init(&gl->gl_lru);
178 else
179 atomic_inc(&lru_count);
180
181 list_add_tail(&gl->gl_lru, &lru_list);
182 spin_unlock(&lru_lock);
183 }
184}
185
186void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
187{
188 spin_lock(&gl->gl_spin);
189 __gfs2_glock_schedule_for_reclaim(gl);
190 spin_unlock(&gl->gl_spin);
191} 188}
192 189
193/** 190/**
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index aea160690e9..6b2f757b928 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -225,11 +225,10 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl,
225 225
226extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state); 226extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
227extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret); 227extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
228extern void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
229extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp); 228extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
230extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip); 229extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
231extern void gfs2_glock_thaw(struct gfs2_sbd *sdp); 230extern void gfs2_glock_thaw(struct gfs2_sbd *sdp);
232extern void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl); 231extern void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
233extern void gfs2_glock_free(struct gfs2_glock *gl); 232extern void gfs2_glock_free(struct gfs2_glock *gl);
234 233
235extern int __init gfs2_glock_init(void); 234extern int __init gfs2_glock_init(void);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 51d27f00ebb..611a51d476b 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -40,7 +40,7 @@ static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh)
40{ 40{
41 struct gfs2_bufdata *bd; 41 struct gfs2_bufdata *bd;
42 42
43 gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); 43 BUG_ON(!current->journal_info);
44 44
45 clear_buffer_dirty(bh); 45 clear_buffer_dirty(bh);
46 if (test_set_buffer_pinned(bh)) 46 if (test_set_buffer_pinned(bh))
@@ -65,6 +65,7 @@ static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh)
65 * @sdp: the filesystem the buffer belongs to 65 * @sdp: the filesystem the buffer belongs to
66 * @bh: The buffer to unpin 66 * @bh: The buffer to unpin
67 * @ai: 67 * @ai:
68 * @flags: The inode dirty flags
68 * 69 *
69 */ 70 */
70 71
@@ -73,10 +74,8 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
73{ 74{
74 struct gfs2_bufdata *bd = bh->b_private; 75 struct gfs2_bufdata *bd = bh->b_private;
75 76
76 gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); 77 BUG_ON(!buffer_uptodate(bh));
77 78 BUG_ON(!buffer_pinned(bh));
78 if (!buffer_pinned(bh))
79 gfs2_assert_withdraw(sdp, 0);
80 79
81 lock_buffer(bh); 80 lock_buffer(bh);
82 mark_buffer_dirty(bh); 81 mark_buffer_dirty(bh);
@@ -95,8 +94,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
95 list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); 94 list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list);
96 spin_unlock(&sdp->sd_ail_lock); 95 spin_unlock(&sdp->sd_ail_lock);
97 96
98 if (test_and_clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags)) 97 clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
99 gfs2_glock_schedule_for_reclaim(bd->bd_gl);
100 trace_gfs2_pin(bd, 0); 98 trace_gfs2_pin(bd, 0);
101 unlock_buffer(bh); 99 unlock_buffer(bh);
102 atomic_dec(&sdp->sd_log_pinned); 100 atomic_dec(&sdp->sd_log_pinned);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index b643c14caff..7273ad3c85b 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -392,6 +392,7 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp)
392 392
393 if (gl) { 393 if (gl) {
394 gl->gl_object = NULL; 394 gl->gl_object = NULL;
395 gfs2_glock_add_to_lru(gl);
395 gfs2_glock_put(gl); 396 gfs2_glock_put(gl);
396 } 397 }
397 398
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index d827b934cbd..b62c8427672 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1401,6 +1401,7 @@ out:
1401 end_writeback(inode); 1401 end_writeback(inode);
1402 1402
1403 ip->i_gl->gl_object = NULL; 1403 ip->i_gl->gl_object = NULL;
1404 gfs2_glock_add_to_lru(ip->i_gl);
1404 gfs2_glock_put(ip->i_gl); 1405 gfs2_glock_put(ip->i_gl);
1405 ip->i_gl = NULL; 1406 ip->i_gl = NULL;
1406 if (ip->i_iopen_gh.gh_gl) { 1407 if (ip->i_iopen_gh.gh_gl) {