unlock_rsb(r);
 }
 
-struct rsbtbl_iter {
-       struct dlm_rsb *rsb;
-       unsigned bucket;
-       int format;
-       int header;
-};
+static const struct seq_operations format1_seq_ops;
+static const struct seq_operations format2_seq_ops;
+static const struct seq_operations format3_seq_ops;
+static const struct seq_operations format4_seq_ops;
 
 /*
  * If the buffer is full, seq_printf can be called again, but it
 
 static int table_seq_show(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsbtbl_iter *ri = iter_ptr;
-
-       switch (ri->format) {
-       case 1:
-               print_format1(ri->rsb, seq);
-               break;
-       case 2:
-               if (ri->header) {
-                       seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
-                       ri->header = 0;
-               }
-               print_format2(ri->rsb, seq);
-               break;
-       case 3:
-               if (ri->header) {
-                       seq_puts(seq, "rsb ptr nodeid first_lkid flags !root_list_empty !recover_list_empty recover_locks_count len\n");
-                       ri->header = 0;
-               }
-               print_format3(ri->rsb, seq);
-               break;
-       case 4:
-               if (ri->header) {
-                       seq_puts(seq, "rsb ptr nodeid master_nodeid dir_nodeid our_nodeid toss_time flags len str|hex name\n");
-                       ri->header = 0;
-               }
-               print_format4(ri->rsb, seq);
-               break;
-       }
+       struct dlm_rsb *rsb = list_entry(iter_ptr, struct dlm_rsb, res_rsbs_list);
+
+       if (seq->op == &format1_seq_ops)
+               print_format1(rsb, seq);
+       else if (seq->op == &format2_seq_ops)
+               print_format2(rsb, seq);
+       else if (seq->op == &format3_seq_ops)
+               print_format3(rsb, seq);
+       else if (seq->op == &format4_seq_ops)
+               print_format4(rsb, seq);
 
        return 0;
 }
 
-static const struct seq_operations format1_seq_ops;
-static const struct seq_operations format2_seq_ops;
-static const struct seq_operations format3_seq_ops;
-static const struct seq_operations format4_seq_ops;
-
 static void *table_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct rb_root *tree;
-       struct rb_node *node;
        struct dlm_ls *ls = seq->private;
-       struct rsbtbl_iter *ri;
-       struct dlm_rsb *r;
-       loff_t n = *pos;
-       unsigned bucket, entry;
-       int toss = (seq->op == &format4_seq_ops);
-
-       bucket = n >> 32;
-       entry = n & ((1LL << 32) - 1);
-
-       if (bucket >= ls->ls_rsbtbl_size)
-               return NULL;
-
-       ri = kzalloc(sizeof(*ri), GFP_NOFS);
-       if (!ri)
-               return NULL;
-       if (n == 0)
-               ri->header = 1;
-       if (seq->op == &format1_seq_ops)
-               ri->format = 1;
-       if (seq->op == &format2_seq_ops)
-               ri->format = 2;
-       if (seq->op == &format3_seq_ops)
-               ri->format = 3;
-       if (seq->op == &format4_seq_ops)
-               ri->format = 4;
-
-       tree = &ls->ls_rsbtbl[bucket].r;
+       struct list_head *list;
 
-       spin_lock_bh(&ls->ls_rsbtbl_lock);
-       if (!RB_EMPTY_ROOT(tree)) {
-               for (node = rb_first(tree); node; node = rb_next(node)) {
-                       r = rb_entry(node, struct dlm_rsb, res_hashnode);
-                       if (toss) {
-                               if (!rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       } else {
-                               if (rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       }
-
-                       if (!entry--) {
-                               dlm_hold_rsb(r);
-                               ri->rsb = r;
-                               ri->bucket = bucket;
-                               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-                               return ri;
-                       }
-               }
+       if (!*pos) {
+               if (seq->op == &format2_seq_ops)
+                       seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
+               else if (seq->op == &format3_seq_ops)
+                       seq_puts(seq, "rsb ptr nodeid first_lkid flags !root_list_empty !recover_list_empty recover_locks_count len\n");
+               else if (seq->op == &format4_seq_ops)
+                       seq_puts(seq, "rsb ptr nodeid master_nodeid dir_nodeid our_nodeid toss_time flags len str|hex name\n");
        }
-       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-
-       /*
-        * move to the first rsb in the next non-empty bucket
-        */
-
-       /* zero the entry */
-       n &= ~((1LL << 32) - 1);
 
-       while (1) {
-               bucket++;
-               n += 1LL << 32;
+       if (seq->op == &format4_seq_ops)
+               list = &ls->ls_toss;
+       else
+               list = &ls->ls_keep;
 
-               if (bucket >= ls->ls_rsbtbl_size) {
-                       kfree(ri);
-                       return NULL;
-               }
-               tree = &ls->ls_rsbtbl[bucket].r;
-
-               spin_lock_bh(&ls->ls_rsbtbl_lock);
-               if (!RB_EMPTY_ROOT(tree)) {
-                       node = rb_first(tree);
-                       r = rb_entry(node, struct dlm_rsb, res_hashnode);
-                       if (toss) {
-                               if (!rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       } else {
-                               if (rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       }
-
-                       dlm_hold_rsb(r);
-                       ri->rsb = r;
-                       ri->bucket = bucket;
-                       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-                       *pos = n;
-                       return ri;
-               }
-               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-       }
+       spin_lock_bh(&ls->ls_rsbtbl_lock);
+       return seq_list_start(list, *pos);
 }
 
 static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
 {
        struct dlm_ls *ls = seq->private;
-       struct rsbtbl_iter *ri = iter_ptr;
-       struct rb_root *tree;
-       struct rb_node *next;
-       struct dlm_rsb *r, *rp;
-       loff_t n = *pos;
-       unsigned bucket;
-       int toss = (seq->op == &format4_seq_ops);
-
-       bucket = n >> 32;
-
-       /*
-        * move to the next rsb in the same bucket
-        */
-
-       spin_lock_bh(&ls->ls_rsbtbl_lock);
-       rp = ri->rsb;
-       next = rb_next(&rp->res_hashnode);
-
-       if (next) {
-               r = rb_entry(next, struct dlm_rsb, res_hashnode);
-               dlm_hold_rsb(r);
-               ri->rsb = r;
-               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-               dlm_put_rsb(rp);
-               ++*pos;
-               return ri;
-       }
-       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-       dlm_put_rsb(rp);
-
-       /*
-        * move to the first rsb in the next non-empty bucket
-        */
+       struct list_head *list;
 
-       /* zero the entry */
-       n &= ~((1LL << 32) - 1);
-
-       while (1) {
-               bucket++;
-               n += 1LL << 32;
+       if (seq->op == &format4_seq_ops)
+               list = &ls->ls_toss;
+       else
+               list = &ls->ls_keep;
 
-               if (bucket >= ls->ls_rsbtbl_size) {
-                       kfree(ri);
-                       ++*pos;
-                       return NULL;
-               }
-               tree = &ls->ls_rsbtbl[bucket].r;
-
-               spin_lock_bh(&ls->ls_rsbtbl_lock);
-               if (!RB_EMPTY_ROOT(tree)) {
-                       next = rb_first(tree);
-                       r = rb_entry(next, struct dlm_rsb, res_hashnode);
-                       if (toss) {
-                               if (!rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       } else {
-                               if (rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       }
-                       dlm_hold_rsb(r);
-                       ri->rsb = r;
-                       ri->bucket = bucket;
-                       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-                       *pos = n;
-                       return ri;
-               }
-               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-       }
+       return seq_list_next(iter_ptr, list, pos);
 }
 
 static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsbtbl_iter *ri = iter_ptr;
+       struct dlm_ls *ls = seq->private;
 
-       if (ri) {
-               dlm_put_rsb(ri->rsb);
-               kfree(ri);
-       }
+       spin_unlock_bh(&ls->ls_rsbtbl_lock);
 }
 
 static const struct seq_operations format1_seq_ops = {
 
        struct list_head        res_convertqueue;
        struct list_head        res_waitqueue;
 
+       struct list_head        res_rsbs_list;
        struct list_head        res_root_list;      /* used for recovery */
        struct list_head        res_masters_list;   /* used for recovery */
        struct list_head        res_recover_list;   /* used for recovery */
        spinlock_t              ls_rsbtbl_lock;
        uint32_t                ls_rsbtbl_size;
 
+       struct list_head        ls_toss;
+       struct list_head        ls_keep;
+
        spinlock_t              ls_waiters_lock;
        struct list_head        ls_waiters;     /* lkbs needing a reply */
 
 
                r->res_first_lkid = 0;
        }
 
+       list_move(&r->res_rsbs_list, &ls->ls_keep);
        rsb_clear_flag(r, RSB_TOSS);
        goto out_unlock;
 
 
  out_add:
        error = rsb_insert(r, &ls->ls_rsbtbl[b].r);
+       if (!error)
+               list_add(&r->res_rsbs_list, &ls->ls_keep);
  out_unlock:
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
  out:
                r->res_nodeid = 0;
        }
 
+       list_move(&r->res_rsbs_list, &ls->ls_keep);
        rsb_clear_flag(r, RSB_TOSS);
        goto out_unlock;
 
        kref_init(&r->res_ref);
 
        error = rsb_insert(r, &ls->ls_rsbtbl[b].r);
+       if (!error)
+               list_add(&r->res_rsbs_list, &ls->ls_keep);
  out_unlock:
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
  out:
                goto retry;
        }
 
+       list_add(&r->res_rsbs_list, &ls->ls_toss);
+
        if (result)
                *result = DLM_LU_ADD;
        *r_nodeid = from_nodeid;
 
 static void dlm_dump_rsb_hash(struct dlm_ls *ls, uint32_t hash)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
-       int i;
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = rb_next(n)) {
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (rsb_flag(r, RSB_TOSS))
-                               continue;
-
-                       if (r->res_hash == hash)
-                               dlm_dump_rsb(r);
-               }
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
+               if (r->res_hash == hash)
+                       dlm_dump_rsb(r);
        }
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
 }
        kref_init(&r->res_ref);
        WARN_ON(rsb_flag(r, RSB_TOSS));
        rsb_set_flag(r, RSB_TOSS);
+       list_move(&r->res_rsbs_list, &ls->ls_toss);
        r->res_toss_time = jiffies;
        set_bit(DLM_RTF_SHRINK_BIT, &ls->ls_rsbtbl[r->res_bucket].flags);
        if (r->res_lvbptr) {
                        continue;
                }
 
+               list_del(&r->res_rsbs_list);
                rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].r);
                dlm_free_rsb(r);
        }
                        continue;
                }
 
+               list_del(&r->res_rsbs_list);
                rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].r);
                send_remove(r);
                spin_unlock_bh(&ls->ls_rsbtbl_lock);
        }
 
        if (kref_put(&r->res_ref, kill_rsb)) {
+               list_del(&r->res_rsbs_list);
                rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].r);
                spin_unlock_bh(&ls->ls_rsbtbl_lock);
                dlm_free_rsb(r);
                          lkb_count, nodes_count);
 }
 
-static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls, int bucket)
+static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (n = rb_first(&ls->ls_rsbtbl[bucket].r); n; n = rb_next(n)) {
-               r = rb_entry(n, struct dlm_rsb, res_hashnode);
-               if (rsb_flag(r, RSB_TOSS))
-                       continue;
-
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
                if (!rsb_flag(r, RSB_RECOVER_GRANT))
                        continue;
                if (!is_master(r)) {
 void dlm_recover_grant(struct dlm_ls *ls)
 {
        struct dlm_rsb *r;
-       int bucket = 0;
        unsigned int count = 0;
        unsigned int rsb_count = 0;
        unsigned int lkb_count = 0;
 
        while (1) {
-               r = find_grant_rsb(ls, bucket);
-               if (!r) {
-                       if (bucket == ls->ls_rsbtbl_size - 1)
-                               break;
-                       bucket++;
-                       continue;
-               }
+               r = find_grant_rsb(ls);
+               if (!r)
+                       break;
+
                rsb_count++;
                count = 0;
                lock_rsb(r);
 
         */
        ls->ls_exflags = (flags & ~(DLM_LSFL_FS | DLM_LSFL_NEWEXCL));
 
+       INIT_LIST_HEAD(&ls->ls_toss);
+       INIT_LIST_HEAD(&ls->ls_keep);
        spin_lock_init(&ls->ls_rsbtbl_lock);
        size = READ_ONCE(dlm_config.ci_rsbtbl_size);
        ls->ls_rsbtbl_size = size;
        for (i = 0; i < ls->ls_rsbtbl_size; i++) {
                while ((n = rb_first(&ls->ls_rsbtbl[i].r))) {
                        rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
+                       list_del(&rsb->res_rsbs_list);
                        rb_erase(n, &ls->ls_rsbtbl[i].r);
                        dlm_free_rsb(rsb);
                }
 
 
 void dlm_clear_toss(struct dlm_ls *ls)
 {
-       struct rb_node *n, *next;
-       struct dlm_rsb *r;
+       struct dlm_rsb *r, *safe;
        unsigned int count = 0;
-       int i;
-
-       spin_lock(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = next) {
-                       next = rb_next(n);
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (!rsb_flag(r, RSB_TOSS))
-                               continue;
-
-                       rb_erase(n, &ls->ls_rsbtbl[i].r);
-                       dlm_free_rsb(r);
-                       count++;
-               }
+
+       spin_lock_bh(&ls->ls_rsbtbl_lock);
+       list_for_each_entry_safe(r, safe, &ls->ls_toss, res_rsbs_list) {
+               list_del(&r->res_rsbs_list);
+               rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[r->res_bucket].r);
+               dlm_free_rsb(r);
+               count++;
        }
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
 
 
 
 static int dlm_create_masters_list(struct dlm_ls *ls)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
-       int i, error = 0;
+       int error = 0;
 
        write_lock_bh(&ls->ls_masters_lock);
        if (!list_empty(&ls->ls_masters_list)) {
        }
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = rb_next(n)) {
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (rsb_flag(r, RSB_TOSS) || r->res_nodeid)
-                               continue;
-
-                       list_add(&r->res_masters_list, &ls->ls_masters_list);
-                       dlm_hold_rsb(r);
-               }
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
+               if (r->res_nodeid)
+                       continue;
+
+               list_add(&r->res_masters_list, &ls->ls_masters_list);
+               dlm_hold_rsb(r);
        }
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
  out:
 
 static void dlm_create_root_list(struct dlm_ls *ls, struct list_head *root_list)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
-       int i;
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = rb_next(n)) {
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (WARN_ON_ONCE(rsb_flag(r, RSB_TOSS)))
-                               continue;
-
-                       list_add(&r->res_root_list, root_list);
-                       dlm_hold_rsb(r);
-               }
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
+               list_add(&r->res_root_list, root_list);
+               dlm_hold_rsb(r);
        }
+
+       WARN_ON_ONCE(!list_empty(&ls->ls_toss));
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
 }