- spin_lock(&gl->gl_spin);
- if (find_first_holder(gl) == NULL &&
- gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) {
- handle_callback(gl, LM_ST_UNLOCKED, 0, 0);
- done_callback = 1;
+ spin_lock(&lru_lock);
+ while(nr && !list_empty(&lru_list)) {
+ gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru);
+ list_del_init(&gl->gl_lru);
+ atomic_dec(&lru_count);
+
+ /* Test for being demotable */
+ if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
+ gfs2_glock_hold(gl);
+ got_ref = 1;
+ spin_unlock(&lru_lock);
+ spin_lock(&gl->gl_spin);
+ may_demote = demote_ok(gl);
+ spin_unlock(&gl->gl_spin);
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+ if (may_demote) {
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
+ nr--;
+ if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+ gfs2_glock_put(gl);
+ }
+ spin_lock(&lru_lock);
+ if (may_demote)
+ continue;
+ }
+ if (list_empty(&gl->gl_lru) &&
+ (atomic_read(&gl->gl_ref) <= (2 + got_ref))) {
+ nr_skipped++;
+ list_add(&gl->gl_lru, &skipped);
+ }
+ if (got_ref) {
+ spin_unlock(&lru_lock);
+ gfs2_glock_put(gl);
+ spin_lock(&lru_lock);
+ got_ref = 0;
+ }