aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm/lock.c')
-rw-r--r--fs/dlm/lock.c87
1 files changed, 70 insertions, 17 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 83b5e32514e1..d47183043c59 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);