aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2009-07-10 19:04:24 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-07-30 06:00:09 -0400
commit8ff22a6f9bdaac87c0eeb1d56c736181f11b4221 (patch)
tree00b0ad7afe45497d251adb244baf6875a0744985 /fs
parent1e19a19584b332eb92a573b66b7342fb97e67507 (diff)
GFS2: Don't put unlikely reclaim candidates on the reclaim list.
GFS2 was placing far too many glocks on the reclaim list that were not good candidates for freeing up from cache. These locks would sit there and repeatedly get scanned to see if they could be reclaimed, wasting a lot of time when there was memory pressure. This fix does more checks on the locks to see if they are actually likely to be removable from cache. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/glock.c72
1 files changed, 46 insertions, 26 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 827136ee794c..f041a89e1ab8 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -174,6 +174,26 @@ static void gfs2_glock_hold(struct gfs2_glock *gl)
174} 174}
175 175
176/** 176/**
177 * demote_ok - Check to see if it's ok to unlock a glock
178 * @gl: the glock
179 *
180 * Returns: 1 if it's ok
181 */
182
183static int demote_ok(const struct gfs2_glock *gl)
184{
185 const struct gfs2_glock_operations *glops = gl->gl_ops;
186
187 if (gl->gl_state == LM_ST_UNLOCKED)
188 return 0;
189 if (!list_empty(&gl->gl_holders))
190 return 0;
191 if (glops->go_demote_ok)
192 return glops->go_demote_ok(gl);
193 return 1;
194}
195
196/**
177 * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list 197 * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
178 * @gl: the glock 198 * @gl: the glock
179 * 199 *
@@ -181,8 +201,13 @@ static void gfs2_glock_hold(struct gfs2_glock *gl)
181 201
182static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) 202static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
183{ 203{
204 int may_reclaim;
205 may_reclaim = (demote_ok(gl) &&
206 (atomic_read(&gl->gl_ref) == 1 ||
207 (gl->gl_name.ln_type == LM_TYPE_INODE &&
208 atomic_read(&gl->gl_ref) <= 2)));
184 spin_lock(&lru_lock); 209 spin_lock(&lru_lock);
185 if (list_empty(&gl->gl_lru) && gl->gl_state != LM_ST_UNLOCKED) { 210 if (list_empty(&gl->gl_lru) && may_reclaim) {
186 list_add_tail(&gl->gl_lru, &lru_list); 211 list_add_tail(&gl->gl_lru, &lru_list);
187 atomic_inc(&lru_count); 212 atomic_inc(&lru_count);
188 } 213 }
@@ -190,6 +215,21 @@ static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
190} 215}
191 216
192/** 217/**
218 * gfs2_glock_put_nolock() - Decrement reference count on glock
219 * @gl: The glock to put
220 *
221 * This function should only be used if the caller has its own reference
222 * to the glock, in addition to the one it is dropping.
223 */
224
225static void gfs2_glock_put_nolock(struct gfs2_glock *gl)
226{
227 if (atomic_dec_and_test(&gl->gl_ref))
228 GLOCK_BUG_ON(gl, 1);
229 gfs2_glock_schedule_for_reclaim(gl);
230}
231
232/**
193 * gfs2_glock_put() - Decrement reference count on glock 233 * gfs2_glock_put() - Decrement reference count on glock
194 * @gl: The glock to put 234 * @gl: The glock to put
195 * 235 *
@@ -214,9 +254,9 @@ int gfs2_glock_put(struct gfs2_glock *gl)
214 rv = 1; 254 rv = 1;
215 goto out; 255 goto out;
216 } 256 }
217 /* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */ 257 spin_lock(&gl->gl_spin);
218 if (atomic_read(&gl->gl_ref) == 2) 258 gfs2_glock_schedule_for_reclaim(gl);
219 gfs2_glock_schedule_for_reclaim(gl); 259 spin_unlock(&gl->gl_spin);
220 write_unlock(gl_lock_addr(gl->gl_hash)); 260 write_unlock(gl_lock_addr(gl->gl_hash));
221out: 261out:
222 return rv; 262 return rv;
@@ -398,7 +438,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
398 if (held2) 438 if (held2)
399 gfs2_glock_hold(gl); 439 gfs2_glock_hold(gl);
400 else 440 else
401 gfs2_glock_put(gl); 441 gfs2_glock_put_nolock(gl);
402 } 442 }
403 443
404 gl->gl_state = new_state; 444 gl->gl_state = new_state;
@@ -633,7 +673,7 @@ out:
633out_sched: 673out_sched:
634 gfs2_glock_hold(gl); 674 gfs2_glock_hold(gl);
635 if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) 675 if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
636 gfs2_glock_put(gl); 676 gfs2_glock_put_nolock(gl);
637out_unlock: 677out_unlock:
638 clear_bit(GLF_LOCK, &gl->gl_flags); 678 clear_bit(GLF_LOCK, &gl->gl_flags);
639 goto out; 679 goto out;
@@ -1274,26 +1314,6 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
1274 gfs2_glock_put(gl); 1314 gfs2_glock_put(gl);
1275} 1315}
1276 1316
1277/**
1278 * demote_ok - Check to see if it's ok to unlock a glock
1279 * @gl: the glock
1280 *
1281 * Returns: 1 if it's ok
1282 */
1283
1284static int demote_ok(const struct gfs2_glock *gl)
1285{
1286 const struct gfs2_glock_operations *glops = gl->gl_ops;
1287
1288 if (gl->gl_state == LM_ST_UNLOCKED)
1289 return 0;
1290 if (!list_empty(&gl->gl_holders))
1291 return 0;
1292 if (glops->go_demote_ok)
1293 return glops->go_demote_ok(gl);
1294 return 1;
1295}
1296
1297 1317
1298static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) 1318static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
1299{ 1319{