diff options
| -rw-r--r-- | fs/gfs2/glock.c | 72 |
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 | |||
| 183 | static 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 | ||
| 182 | static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | 202 | static 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 | |||
| 225 | static 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)); |
| 221 | out: | 261 | out: |
| 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: | |||
| 633 | out_sched: | 673 | out_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); |
| 637 | out_unlock: | 677 | out_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 | |||
| 1284 | static 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 | ||
| 1298 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | 1318 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) |
| 1299 | { | 1319 | { |
