aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/lock.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2011-07-06 18:00:54 -0400
committerDavid Teigland <teigland@redhat.com>2011-07-11 09:43:45 -0400
commit3d6aa675fff9eee5a6339d67b355b63a6d69565f (patch)
treef401792f4e92f2473d361bfb185c517838ab2032 /fs/dlm/lock.c
parenta22ca4806822154c163c6f220f4c2a05adf96fc7 (diff)
dlm: keep lkbs in idr
This is simpler and quicker than the hash table, and avoids needing to search the hash list for every new lkid to check if it's used. Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/lock.c')
-rw-r--r--fs/dlm/lock.c69
1 files changed, 24 insertions, 45 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 3c723489079a..784cde417ced 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -580,9 +580,8 @@ static void detach_lkb(struct dlm_lkb *lkb)
580 580
581static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) 581static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
582{ 582{
583 struct dlm_lkb *lkb, *tmp; 583 struct dlm_lkb *lkb;
584 uint32_t lkid = 0; 584 int rv, id;
585 uint16_t bucket;
586 585
587 lkb = dlm_allocate_lkb(ls); 586 lkb = dlm_allocate_lkb(ls);
588 if (!lkb) 587 if (!lkb)
@@ -596,58 +595,38 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
596 INIT_LIST_HEAD(&lkb->lkb_time_list); 595 INIT_LIST_HEAD(&lkb->lkb_time_list);
597 INIT_LIST_HEAD(&lkb->lkb_astqueue); 596 INIT_LIST_HEAD(&lkb->lkb_astqueue);
598 597
599 get_random_bytes(&bucket, sizeof(bucket)); 598 retry:
600 bucket &= (ls->ls_lkbtbl_size - 1); 599 rv = idr_pre_get(&ls->ls_lkbidr, GFP_NOFS);
601 600 if (!rv)
602 write_lock(&ls->ls_lkbtbl[bucket].lock); 601 return -ENOMEM;
603 602
604 /* counter can roll over so we must verify lkid is not in use */ 603 spin_lock(&ls->ls_lkbidr_spin);
604 rv = idr_get_new_above(&ls->ls_lkbidr, lkb, 1, &id);
605 if (!rv)
606 lkb->lkb_id = id;
607 spin_unlock(&ls->ls_lkbidr_spin);
605 608
606 while (lkid == 0) { 609 if (rv == -EAGAIN)
607 lkid = (bucket << 16) | ls->ls_lkbtbl[bucket].counter++; 610 goto retry;
608 611
609 list_for_each_entry(tmp, &ls->ls_lkbtbl[bucket].list, 612 if (rv < 0) {
610 lkb_idtbl_list) { 613 log_error(ls, "create_lkb idr error %d", rv);
611 if (tmp->lkb_id != lkid) 614 return rv;
612 continue;
613 lkid = 0;
614 break;
615 }
616 } 615 }
617 616
618 lkb->lkb_id = lkid;
619 list_add(&lkb->lkb_idtbl_list, &ls->ls_lkbtbl[bucket].list);
620 write_unlock(&ls->ls_lkbtbl[bucket].lock);
621
622 *lkb_ret = lkb; 617 *lkb_ret = lkb;
623 return 0; 618 return 0;
624} 619}
625 620
626static struct dlm_lkb *__find_lkb(struct dlm_ls *ls, uint32_t lkid)
627{
628 struct dlm_lkb *lkb;
629 uint16_t bucket = (lkid >> 16);
630
631 list_for_each_entry(lkb, &ls->ls_lkbtbl[bucket].list, lkb_idtbl_list) {
632 if (lkb->lkb_id == lkid)
633 return lkb;
634 }
635 return NULL;
636}
637
638static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret) 621static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
639{ 622{
640 struct dlm_lkb *lkb; 623 struct dlm_lkb *lkb;
641 uint16_t bucket = (lkid >> 16);
642
643 if (bucket >= ls->ls_lkbtbl_size)
644 return -EBADSLT;
645 624
646 read_lock(&ls->ls_lkbtbl[bucket].lock); 625 spin_lock(&ls->ls_lkbidr_spin);
647 lkb = __find_lkb(ls, lkid); 626 lkb = idr_find(&ls->ls_lkbidr, lkid);
648 if (lkb) 627 if (lkb)
649 kref_get(&lkb->lkb_ref); 628 kref_get(&lkb->lkb_ref);
650 read_unlock(&ls->ls_lkbtbl[bucket].lock); 629 spin_unlock(&ls->ls_lkbidr_spin);
651 630
652 *lkb_ret = lkb; 631 *lkb_ret = lkb;
653 return lkb ? 0 : -ENOENT; 632 return lkb ? 0 : -ENOENT;
@@ -668,12 +647,12 @@ static void kill_lkb(struct kref *kref)
668 647
669static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb) 648static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
670{ 649{
671 uint16_t bucket = (lkb->lkb_id >> 16); 650 uint32_t lkid = lkb->lkb_id;
672 651
673 write_lock(&ls->ls_lkbtbl[bucket].lock); 652 spin_lock(&ls->ls_lkbidr_spin);
674 if (kref_put(&lkb->lkb_ref, kill_lkb)) { 653 if (kref_put(&lkb->lkb_ref, kill_lkb)) {
675 list_del(&lkb->lkb_idtbl_list); 654 idr_remove(&ls->ls_lkbidr, lkid);
676 write_unlock(&ls->ls_lkbtbl[bucket].lock); 655 spin_unlock(&ls->ls_lkbidr_spin);
677 656
678 detach_lkb(lkb); 657 detach_lkb(lkb);
679 658
@@ -683,7 +662,7 @@ static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
683 dlm_free_lkb(lkb); 662 dlm_free_lkb(lkb);
684 return 1; 663 return 1;
685 } else { 664 } else {
686 write_unlock(&ls->ls_lkbtbl[bucket].lock); 665 spin_unlock(&ls->ls_lkbidr_spin);
687 return 0; 666 return 0;
688 } 667 }
689} 668}