aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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{