aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2011-10-26 16:24:55 -0400
committerDavid Teigland <teigland@redhat.com>2011-11-18 11:20:15 -0500
commit9beb3bf5a92bb8fc6503f844bf0772df29f14a02 (patch)
treec60963c27d0a93ae1f572e6fda9c090a4a702d4e /fs
parentc3b92c8787367a8bb53d57d9789b558f1295cc96 (diff)
dlm: convert rsb list to rb_tree
Change the linked lists to rb_tree's in the rsb hash table to speed up searches. Slow rsb searches were having a large impact on gfs2 performance due to the large number of dlm locks gfs2 uses. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/dlm/debug_fs.c28
-rw-r--r--fs/dlm/dlm_internal.h9
-rw-r--r--fs/dlm/lock.c87
-rw-r--r--fs/dlm/lockspace.c23
-rw-r--r--fs/dlm/recover.c21
5 files changed, 113 insertions, 55 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 59779237e2b..3dca2b39e83 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -393,6 +393,7 @@ static const struct seq_operations format3_seq_ops;
393 393
394static void *table_seq_start(struct seq_file *seq, loff_t *pos) 394static void *table_seq_start(struct seq_file *seq, loff_t *pos)
395{ 395{
396 struct rb_node *node;
396 struct dlm_ls *ls = seq->private; 397 struct dlm_ls *ls = seq->private;
397 struct rsbtbl_iter *ri; 398 struct rsbtbl_iter *ri;
398 struct dlm_rsb *r; 399 struct dlm_rsb *r;
@@ -418,9 +419,10 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos)
418 ri->format = 3; 419 ri->format = 3;
419 420
420 spin_lock(&ls->ls_rsbtbl[bucket].lock); 421 spin_lock(&ls->ls_rsbtbl[bucket].lock);
421 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) { 422 if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
422 list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list, 423 for (node = rb_first(&ls->ls_rsbtbl[bucket].keep); node;
423 res_hashchain) { 424 node = rb_next(node)) {
425 r = rb_entry(node, struct dlm_rsb, res_hashnode);
424 if (!entry--) { 426 if (!entry--) {
425 dlm_hold_rsb(r); 427 dlm_hold_rsb(r);
426 ri->rsb = r; 428 ri->rsb = r;
@@ -449,9 +451,9 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos)
449 } 451 }
450 452
451 spin_lock(&ls->ls_rsbtbl[bucket].lock); 453 spin_lock(&ls->ls_rsbtbl[bucket].lock);
452 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) { 454 if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
453 r = list_first_entry(&ls->ls_rsbtbl[bucket].list, 455 node = rb_first(&ls->ls_rsbtbl[bucket].keep);
454 struct dlm_rsb, res_hashchain); 456 r = rb_entry(node, struct dlm_rsb, res_hashnode);
455 dlm_hold_rsb(r); 457 dlm_hold_rsb(r);
456 ri->rsb = r; 458 ri->rsb = r;
457 ri->bucket = bucket; 459 ri->bucket = bucket;
@@ -467,7 +469,7 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
467{ 469{
468 struct dlm_ls *ls = seq->private; 470 struct dlm_ls *ls = seq->private;
469 struct rsbtbl_iter *ri = iter_ptr; 471 struct rsbtbl_iter *ri = iter_ptr;
470 struct list_head *next; 472 struct rb_node *next;
471 struct dlm_rsb *r, *rp; 473 struct dlm_rsb *r, *rp;
472 loff_t n = *pos; 474 loff_t n = *pos;
473 unsigned bucket; 475 unsigned bucket;
@@ -480,10 +482,10 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
480 482
481 spin_lock(&ls->ls_rsbtbl[bucket].lock); 483 spin_lock(&ls->ls_rsbtbl[bucket].lock);
482 rp = ri->rsb; 484 rp = ri->rsb;
483 next = rp->res_hashchain.next; 485 next = rb_next(&rp->res_hashnode);
484 486
485 if (next != &ls->ls_rsbtbl[bucket].list) { 487 if (next) {
486 r = list_entry(next, struct dlm_rsb, res_hashchain); 488 r = rb_entry(next, struct dlm_rsb, res_hashnode);
487 dlm_hold_rsb(r); 489 dlm_hold_rsb(r);
488 ri->rsb = r; 490 ri->rsb = r;
489 spin_unlock(&ls->ls_rsbtbl[bucket].lock); 491 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
@@ -511,9 +513,9 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
511 } 513 }
512 514
513 spin_lock(&ls->ls_rsbtbl[bucket].lock); 515 spin_lock(&ls->ls_rsbtbl[bucket].lock);
514 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) { 516 if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
515 r = list_first_entry(&ls->ls_rsbtbl[bucket].list, 517 next = rb_first(&ls->ls_rsbtbl[bucket].keep);
516 struct dlm_rsb, res_hashchain); 518 r = rb_entry(next, struct dlm_rsb, res_hashnode);
517 dlm_hold_rsb(r); 519 dlm_hold_rsb(r);
518 ri->rsb = r; 520 ri->rsb = r;
519 ri->bucket = bucket; 521 ri->bucket = bucket;
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index fe2860c0244..5685a9a5dba 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -103,8 +103,8 @@ struct dlm_dirtable {
103}; 103};
104 104
105struct dlm_rsbtable { 105struct dlm_rsbtable {
106 struct list_head list; 106 struct rb_root keep;
107 struct list_head toss; 107 struct rb_root toss;
108 spinlock_t lock; 108 spinlock_t lock;
109}; 109};
110 110
@@ -285,7 +285,10 @@ struct dlm_rsb {
285 unsigned long res_toss_time; 285 unsigned long res_toss_time;
286 uint32_t res_first_lkid; 286 uint32_t res_first_lkid;
287 struct list_head res_lookup; /* lkbs waiting on first */ 287 struct list_head res_lookup; /* lkbs waiting on first */
288 struct list_head res_hashchain; /* rsbtbl */ 288 union {
289 struct list_head res_hashchain;
290 struct rb_node res_hashnode; /* rsbtbl */
291 };
289 struct list_head res_grantqueue; 292 struct list_head res_grantqueue;
290 struct list_head res_convertqueue; 293 struct list_head res_convertqueue;
291 struct list_head res_waitqueue; 294 struct list_head res_waitqueue;
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 83b5e32514e..d47183043c5 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -56,6 +56,7 @@
56 L: receive_xxxx_reply() <- R: send_xxxx_reply() 56 L: receive_xxxx_reply() <- R: send_xxxx_reply()
57*/ 57*/
58#include <linux/types.h> 58#include <linux/types.h>
59#include <linux/rbtree.h>
59#include <linux/slab.h> 60#include <linux/slab.h>
60#include "dlm_internal.h" 61#include "dlm_internal.h"
61#include <linux/dlm_device.h> 62#include <linux/dlm_device.h>
@@ -380,6 +381,8 @@ static int get_rsb_struct(struct dlm_ls *ls, char *name, int len,
380 381
381 r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain); 382 r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain);
382 list_del(&r->res_hashchain); 383 list_del(&r->res_hashchain);
384 /* Convert the empty list_head to a NULL rb_node for tree usage: */
385 memset(&r->res_hashnode, 0, sizeof(struct rb_node));
383 ls->ls_new_rsb_count--; 386 ls->ls_new_rsb_count--;
384 spin_unlock(&ls->ls_new_rsb_spin); 387 spin_unlock(&ls->ls_new_rsb_spin);
385 388
@@ -388,7 +391,6 @@ static int get_rsb_struct(struct dlm_ls *ls, char *name, int len,
388 memcpy(r->res_name, name, len); 391 memcpy(r->res_name, name, len);
389 mutex_init(&r->res_mutex); 392 mutex_init(&r->res_mutex);
390 393
391 INIT_LIST_HEAD(&r->res_hashchain);
392 INIT_LIST_HEAD(&r->res_lookup); 394 INIT_LIST_HEAD(&r->res_lookup);
393 INIT_LIST_HEAD(&r->res_grantqueue); 395 INIT_LIST_HEAD(&r->res_grantqueue);
394 INIT_LIST_HEAD(&r->res_convertqueue); 396 INIT_LIST_HEAD(&r->res_convertqueue);
@@ -400,14 +402,31 @@ static int get_rsb_struct(struct dlm_ls *ls, char *name, int len,
400 return 0; 402 return 0;
401} 403}
402 404
403static int search_rsb_list(struct list_head *head, char *name, int len, 405static int rsb_cmp(struct dlm_rsb *r, const char *name, int nlen)
406{
407 char maxname[DLM_RESNAME_MAXLEN];
408
409 memset(maxname, 0, DLM_RESNAME_MAXLEN);
410 memcpy(maxname, name, nlen);
411 return memcmp(r->res_name, maxname, DLM_RESNAME_MAXLEN);
412}
413
414static int search_rsb_tree(struct rb_root *tree, char *name, int len,
404 unsigned int flags, struct dlm_rsb **r_ret) 415 unsigned int flags, struct dlm_rsb **r_ret)
405{ 416{
417 struct rb_node *node = tree->rb_node;
406 struct dlm_rsb *r; 418 struct dlm_rsb *r;
407 int error = 0; 419 int error = 0;
408 420 int rc;
409 list_for_each_entry(r, head, res_hashchain) { 421
410 if (len == r->res_length && !memcmp(name, r->res_name, len)) 422 while (node) {
423 r = rb_entry(node, struct dlm_rsb, res_hashnode);
424 rc = rsb_cmp(r, name, len);
425 if (rc < 0)
426 node = node->rb_left;
427 else if (rc > 0)
428 node = node->rb_right;
429 else
411 goto found; 430 goto found;
412 } 431 }
413 *r_ret = NULL; 432 *r_ret = NULL;
@@ -420,22 +439,54 @@ static int search_rsb_list(struct list_head *head, char *name, int len,
420 return error; 439 return error;
421} 440}
422 441
442static int rsb_insert(struct dlm_rsb *rsb, struct rb_root *tree)
443{
444 struct rb_node **newn = &tree->rb_node;
445 struct rb_node *parent = NULL;
446 int rc;
447
448 while (*newn) {
449 struct dlm_rsb *cur = rb_entry(*newn, struct dlm_rsb,
450 res_hashnode);
451
452 parent = *newn;
453 rc = rsb_cmp(cur, rsb->res_name, rsb->res_length);
454 if (rc < 0)
455 newn = &parent->rb_left;
456 else if (rc > 0)
457 newn = &parent->rb_right;
458 else {
459 log_print("rsb_insert match");
460 dlm_dump_rsb(rsb);
461 dlm_dump_rsb(cur);
462 return -EEXIST;
463 }
464 }
465
466 rb_link_node(&rsb->res_hashnode, parent, newn);
467 rb_insert_color(&rsb->res_hashnode, tree);
468 return 0;
469}
470
423static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b, 471static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b,
424 unsigned int flags, struct dlm_rsb **r_ret) 472 unsigned int flags, struct dlm_rsb **r_ret)
425{ 473{
426 struct dlm_rsb *r; 474 struct dlm_rsb *r;
427 int error; 475 int error;
428 476
429 error = search_rsb_list(&ls->ls_rsbtbl[b].list, name, len, flags, &r); 477 error = search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, flags, &r);
430 if (!error) { 478 if (!error) {
431 kref_get(&r->res_ref); 479 kref_get(&r->res_ref);
432 goto out; 480 goto out;
433 } 481 }
434 error = search_rsb_list(&ls->ls_rsbtbl[b].toss, name, len, flags, &r); 482 error = search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, flags, &r);
435 if (error) 483 if (error)
436 goto out; 484 goto out;
437 485
438 list_move(&r->res_hashchain, &ls->ls_rsbtbl[b].list); 486 rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss);
487 error = rsb_insert(r, &ls->ls_rsbtbl[b].keep);
488 if (error)
489 return error;
439 490
440 if (dlm_no_directory(ls)) 491 if (dlm_no_directory(ls))
441 goto out; 492 goto out;
@@ -527,8 +578,7 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
527 nodeid = 0; 578 nodeid = 0;
528 r->res_nodeid = nodeid; 579 r->res_nodeid = nodeid;
529 } 580 }
530 list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list); 581 error = rsb_insert(r, &ls->ls_rsbtbl[bucket].keep);
531 error = 0;
532 out_unlock: 582 out_unlock:
533 spin_unlock(&ls->ls_rsbtbl[bucket].lock); 583 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
534 out: 584 out:
@@ -556,7 +606,8 @@ static void toss_rsb(struct kref *kref)
556 606
557 DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r);); 607 DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r););
558 kref_init(&r->res_ref); 608 kref_init(&r->res_ref);
559 list_move(&r->res_hashchain, &ls->ls_rsbtbl[r->res_bucket].toss); 609 rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[r->res_bucket].keep);
610 rsb_insert(r, &ls->ls_rsbtbl[r->res_bucket].toss);
560 r->res_toss_time = jiffies; 611 r->res_toss_time = jiffies;
561 if (r->res_lvbptr) { 612 if (r->res_lvbptr) {
562 dlm_free_lvb(r->res_lvbptr); 613 dlm_free_lvb(r->res_lvbptr);
@@ -1082,19 +1133,19 @@ static void dir_remove(struct dlm_rsb *r)
1082 r->res_name, r->res_length); 1133 r->res_name, r->res_length);
1083} 1134}
1084 1135
1085/* FIXME: shouldn't this be able to exit as soon as one non-due rsb is 1136/* FIXME: make this more efficient */
1086 found since they are in order of newest to oldest? */
1087 1137
1088static int shrink_bucket(struct dlm_ls *ls, int b) 1138static int shrink_bucket(struct dlm_ls *ls, int b)
1089{ 1139{
1140 struct rb_node *n;
1090 struct dlm_rsb *r; 1141 struct dlm_rsb *r;
1091 int count = 0, found; 1142 int count = 0, found;
1092 1143
1093 for (;;) { 1144 for (;;) {
1094 found = 0; 1145 found = 0;
1095 spin_lock(&ls->ls_rsbtbl[b].lock); 1146 spin_lock(&ls->ls_rsbtbl[b].lock);
1096 list_for_each_entry_reverse(r, &ls->ls_rsbtbl[b].toss, 1147 for (n = rb_first(&ls->ls_rsbtbl[b].toss); n; n = rb_next(n)) {
1097 res_hashchain) { 1148 r = rb_entry(n, struct dlm_rsb, res_hashnode);
1098 if (!time_after_eq(jiffies, r->res_toss_time + 1149 if (!time_after_eq(jiffies, r->res_toss_time +
1099 dlm_config.ci_toss_secs * HZ)) 1150 dlm_config.ci_toss_secs * HZ))
1100 continue; 1151 continue;
@@ -1108,7 +1159,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b)
1108 } 1159 }
1109 1160
1110 if (kref_put(&r->res_ref, kill_rsb)) { 1161 if (kref_put(&r->res_ref, kill_rsb)) {
1111 list_del(&r->res_hashchain); 1162 rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss);
1112 spin_unlock(&ls->ls_rsbtbl[b].lock); 1163 spin_unlock(&ls->ls_rsbtbl[b].lock);
1113 1164
1114 if (is_master(r)) 1165 if (is_master(r))
@@ -4441,10 +4492,12 @@ int dlm_purge_locks(struct dlm_ls *ls)
4441 4492
4442static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket) 4493static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
4443{ 4494{
4495 struct rb_node *n;
4444 struct dlm_rsb *r, *r_ret = NULL; 4496 struct dlm_rsb *r, *r_ret = NULL;
4445 4497
4446 spin_lock(&ls->ls_rsbtbl[bucket].lock); 4498 spin_lock(&ls->ls_rsbtbl[bucket].lock);
4447 list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list, res_hashchain) { 4499 for (n = rb_first(&ls->ls_rsbtbl[bucket].keep); n; n = rb_next(n)) {
4500 r = rb_entry(n, struct dlm_rsb, res_hashnode);
4448 if (!rsb_flag(r, RSB_LOCKS_PURGED)) 4501 if (!rsb_flag(r, RSB_LOCKS_PURGED))
4449 continue; 4502 continue;
4450 hold_rsb(r); 4503 hold_rsb(r);
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a1d8f1af144..1d16a23b0a0 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -457,8 +457,8 @@ static int new_lockspace(const char *name, int namelen, void **lockspace,
457 if (!ls->ls_rsbtbl) 457 if (!ls->ls_rsbtbl)
458 goto out_lsfree; 458 goto out_lsfree;
459 for (i = 0; i < size; i++) { 459 for (i = 0; i < size; i++) {
460 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list); 460 ls->ls_rsbtbl[i].keep.rb_node = NULL;
461 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss); 461 ls->ls_rsbtbl[i].toss.rb_node = NULL;
462 spin_lock_init(&ls->ls_rsbtbl[i].lock); 462 spin_lock_init(&ls->ls_rsbtbl[i].lock);
463 } 463 }
464 464
@@ -685,7 +685,7 @@ static int lockspace_busy(struct dlm_ls *ls, int force)
685static int release_lockspace(struct dlm_ls *ls, int force) 685static int release_lockspace(struct dlm_ls *ls, int force)
686{ 686{
687 struct dlm_rsb *rsb; 687 struct dlm_rsb *rsb;
688 struct list_head *head; 688 struct rb_node *n;
689 int i, busy, rv; 689 int i, busy, rv;
690 690
691 busy = lockspace_busy(ls, force); 691 busy = lockspace_busy(ls, force);
@@ -746,20 +746,15 @@ static int release_lockspace(struct dlm_ls *ls, int force)
746 */ 746 */
747 747
748 for (i = 0; i < ls->ls_rsbtbl_size; i++) { 748 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
749 head = &ls->ls_rsbtbl[i].list; 749 while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) {
750 while (!list_empty(head)) { 750 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
751 rsb = list_entry(head->next, struct dlm_rsb, 751 rb_erase(n, &ls->ls_rsbtbl[i].keep);
752 res_hashchain);
753
754 list_del(&rsb->res_hashchain);
755 dlm_free_rsb(rsb); 752 dlm_free_rsb(rsb);
756 } 753 }
757 754
758 head = &ls->ls_rsbtbl[i].toss; 755 while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) {
759 while (!list_empty(head)) { 756 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
760 rsb = list_entry(head->next, struct dlm_rsb, 757 rb_erase(n, &ls->ls_rsbtbl[i].toss);
761 res_hashchain);
762 list_del(&rsb->res_hashchain);
763 dlm_free_rsb(rsb); 758 dlm_free_rsb(rsb);
764 } 759 }
765 } 760 }
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index 14638235f7b..50467cefdbd 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -715,6 +715,7 @@ void dlm_recover_rsbs(struct dlm_ls *ls)
715 715
716int dlm_create_root_list(struct dlm_ls *ls) 716int dlm_create_root_list(struct dlm_ls *ls)
717{ 717{
718 struct rb_node *n;
718 struct dlm_rsb *r; 719 struct dlm_rsb *r;
719 int i, error = 0; 720 int i, error = 0;
720 721
@@ -727,7 +728,8 @@ int dlm_create_root_list(struct dlm_ls *ls)
727 728
728 for (i = 0; i < ls->ls_rsbtbl_size; i++) { 729 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
729 spin_lock(&ls->ls_rsbtbl[i].lock); 730 spin_lock(&ls->ls_rsbtbl[i].lock);
730 list_for_each_entry(r, &ls->ls_rsbtbl[i].list, res_hashchain) { 731 for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) {
732 r = rb_entry(n, struct dlm_rsb, res_hashnode);
731 list_add(&r->res_root_list, &ls->ls_root_list); 733 list_add(&r->res_root_list, &ls->ls_root_list);
732 dlm_hold_rsb(r); 734 dlm_hold_rsb(r);
733 } 735 }
@@ -741,7 +743,8 @@ int dlm_create_root_list(struct dlm_ls *ls)
741 continue; 743 continue;
742 } 744 }
743 745
744 list_for_each_entry(r, &ls->ls_rsbtbl[i].toss, res_hashchain) { 746 for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = rb_next(n)) {
747 r = rb_entry(n, struct dlm_rsb, res_hashnode);
745 list_add(&r->res_root_list, &ls->ls_root_list); 748 list_add(&r->res_root_list, &ls->ls_root_list);
746 dlm_hold_rsb(r); 749 dlm_hold_rsb(r);
747 } 750 }
@@ -771,16 +774,18 @@ void dlm_release_root_list(struct dlm_ls *ls)
771 774
772void dlm_clear_toss_list(struct dlm_ls *ls) 775void dlm_clear_toss_list(struct dlm_ls *ls)
773{ 776{
774 struct dlm_rsb *r, *safe; 777 struct rb_node *n, *next;
778 struct dlm_rsb *rsb;
775 int i; 779 int i;
776 780
777 for (i = 0; i < ls->ls_rsbtbl_size; i++) { 781 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
778 spin_lock(&ls->ls_rsbtbl[i].lock); 782 spin_lock(&ls->ls_rsbtbl[i].lock);
779 list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss, 783 for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = next) {
780 res_hashchain) { 784 next = rb_next(n);;
781 if (dlm_no_directory(ls) || !is_master(r)) { 785 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
782 list_del(&r->res_hashchain); 786 if (dlm_no_directory(ls) || !is_master(rsb)) {
783 dlm_free_rsb(r); 787 rb_erase(n, &ls->ls_rsbtbl[i].toss);
788 dlm_free_rsb(rsb);
784 } 789 }
785 } 790 }
786 spin_unlock(&ls->ls_rsbtbl[i].lock); 791 spin_unlock(&ls->ls_rsbtbl[i].lock);