Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+79 -122
-7
fs/dlm/config.c
··· 94 94 unsigned int cl_tcp_port; 95 95 unsigned int cl_buffer_size; 96 96 unsigned int cl_rsbtbl_size; 97 - unsigned int cl_lkbtbl_size; 98 97 unsigned int cl_dirtbl_size; 99 98 unsigned int cl_recover_timer; 100 99 unsigned int cl_toss_secs; ··· 108 109 CLUSTER_ATTR_TCP_PORT = 0, 109 110 CLUSTER_ATTR_BUFFER_SIZE, 110 111 CLUSTER_ATTR_RSBTBL_SIZE, 111 - CLUSTER_ATTR_LKBTBL_SIZE, 112 112 CLUSTER_ATTR_DIRTBL_SIZE, 113 113 CLUSTER_ATTR_RECOVER_TIMER, 114 114 CLUSTER_ATTR_TOSS_SECS, ··· 160 162 CLUSTER_ATTR(tcp_port, 1); 161 163 CLUSTER_ATTR(buffer_size, 1); 162 164 CLUSTER_ATTR(rsbtbl_size, 1); 163 - CLUSTER_ATTR(lkbtbl_size, 1); 164 165 CLUSTER_ATTR(dirtbl_size, 1); 165 166 CLUSTER_ATTR(recover_timer, 1); 166 167 CLUSTER_ATTR(toss_secs, 1); ··· 173 176 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, 174 177 [CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr, 175 178 [CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr, 176 - [CLUSTER_ATTR_LKBTBL_SIZE] = &cluster_attr_lkbtbl_size.attr, 177 179 [CLUSTER_ATTR_DIRTBL_SIZE] = &cluster_attr_dirtbl_size.attr, 178 180 [CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr, 179 181 [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr, ··· 442 446 cl->cl_tcp_port = dlm_config.ci_tcp_port; 443 447 cl->cl_buffer_size = dlm_config.ci_buffer_size; 444 448 cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size; 445 - cl->cl_lkbtbl_size = dlm_config.ci_lkbtbl_size; 446 449 cl->cl_dirtbl_size = dlm_config.ci_dirtbl_size; 447 450 cl->cl_recover_timer = dlm_config.ci_recover_timer; 448 451 cl->cl_toss_secs = dlm_config.ci_toss_secs; ··· 1033 1038 #define DEFAULT_TCP_PORT 21064 1034 1039 #define DEFAULT_BUFFER_SIZE 4096 1035 1040 #define DEFAULT_RSBTBL_SIZE 1024 1036 - #define DEFAULT_LKBTBL_SIZE 1024 1037 1041 #define DEFAULT_DIRTBL_SIZE 1024 1038 1042 #define DEFAULT_RECOVER_TIMER 5 1039 1043 #define DEFAULT_TOSS_SECS 10 ··· 1046 1052 .ci_tcp_port = DEFAULT_TCP_PORT, 1047 1053 .ci_buffer_size = DEFAULT_BUFFER_SIZE, 1048 1054 .ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE, 1049 - .ci_lkbtbl_size = DEFAULT_LKBTBL_SIZE, 1050 1055 .ci_dirtbl_size = DEFAULT_DIRTBL_SIZE, 1051 1056 .ci_recover_timer = DEFAULT_RECOVER_TIMER, 1052 1057 .ci_toss_secs = DEFAULT_TOSS_SECS,
-1
fs/dlm/config.h
··· 20 20 int ci_tcp_port; 21 21 int ci_buffer_size; 22 22 int ci_rsbtbl_size; 23 - int ci_lkbtbl_size; 24 23 int ci_dirtbl_size; 25 24 int ci_recover_timer; 26 25 int ci_toss_secs;
+4 -10
fs/dlm/dlm_internal.h
··· 37 37 #include <linux/jhash.h> 38 38 #include <linux/miscdevice.h> 39 39 #include <linux/mutex.h> 40 + #include <linux/idr.h> 40 41 #include <asm/uaccess.h> 41 42 42 43 #include <linux/dlm.h> ··· 53 52 struct dlm_lkb; 54 53 struct dlm_rsb; 55 54 struct dlm_member; 56 - struct dlm_lkbtable; 57 55 struct dlm_rsbtable; 58 56 struct dlm_dirtable; 59 57 struct dlm_direntry; ··· 108 108 spinlock_t lock; 109 109 }; 110 110 111 - struct dlm_lkbtable { 112 - struct list_head list; 113 - rwlock_t lock; 114 - uint16_t counter; 115 - }; 116 111 117 112 /* 118 113 * Lockspace member (per node in a ls) ··· 243 248 int8_t lkb_wait_count; 244 249 int lkb_wait_nodeid; /* for debugging */ 245 250 246 - struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ 247 251 struct list_head lkb_statequeue; /* rsb g/c/w list */ 248 252 struct list_head lkb_rsb_lookup; /* waiting for rsb lookup */ 249 253 struct list_head lkb_wait_reply; /* waiting for remote reply */ ··· 459 465 unsigned long ls_scan_time; 460 466 struct kobject ls_kobj; 461 467 468 + struct idr ls_lkbidr; 469 + spinlock_t ls_lkbidr_spin; 470 + 462 471 struct dlm_rsbtable *ls_rsbtbl; 463 472 uint32_t ls_rsbtbl_size; 464 - 465 - struct dlm_lkbtable *ls_lkbtbl; 466 - uint32_t ls_lkbtbl_size; 467 473 468 474 struct dlm_dirtable *ls_dirtbl; 469 475 uint32_t ls_dirtbl_size;
+24 -45
fs/dlm/lock.c
··· 580 580 581 581 static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) 582 582 { 583 - struct dlm_lkb *lkb, *tmp; 584 - uint32_t lkid = 0; 585 - uint16_t bucket; 583 + struct dlm_lkb *lkb; 584 + int rv, id; 586 585 587 586 lkb = dlm_allocate_lkb(ls); 588 587 if (!lkb) ··· 595 596 INIT_LIST_HEAD(&lkb->lkb_time_list); 596 597 INIT_LIST_HEAD(&lkb->lkb_astqueue); 597 598 598 - get_random_bytes(&bucket, sizeof(bucket)); 599 - bucket &= (ls->ls_lkbtbl_size - 1); 599 + retry: 600 + rv = idr_pre_get(&ls->ls_lkbidr, GFP_NOFS); 601 + if (!rv) 602 + return -ENOMEM; 600 603 601 - write_lock(&ls->ls_lkbtbl[bucket].lock); 604 + spin_lock(&ls->ls_lkbidr_spin); 605 + rv = idr_get_new_above(&ls->ls_lkbidr, lkb, 1, &id); 606 + if (!rv) 607 + lkb->lkb_id = id; 608 + spin_unlock(&ls->ls_lkbidr_spin); 602 609 603 - /* counter can roll over so we must verify lkid is not in use */ 610 + if (rv == -EAGAIN) 611 + goto retry; 604 612 605 - while (lkid == 0) { 606 - lkid = (bucket << 16) | ls->ls_lkbtbl[bucket].counter++; 607 - 608 - list_for_each_entry(tmp, &ls->ls_lkbtbl[bucket].list, 609 - lkb_idtbl_list) { 610 - if (tmp->lkb_id != lkid) 611 - continue; 612 - lkid = 0; 613 - break; 614 - } 613 + if (rv < 0) { 614 + log_error(ls, "create_lkb idr error %d", rv); 615 + return rv; 615 616 } 616 - 617 - lkb->lkb_id = lkid; 618 - list_add(&lkb->lkb_idtbl_list, &ls->ls_lkbtbl[bucket].list); 619 - write_unlock(&ls->ls_lkbtbl[bucket].lock); 620 617 621 618 *lkb_ret = lkb; 622 619 return 0; 623 620 } 624 621 625 - static struct dlm_lkb *__find_lkb(struct dlm_ls *ls, uint32_t lkid) 626 - { 627 - struct dlm_lkb *lkb; 628 - uint16_t bucket = (lkid >> 16); 629 - 630 - list_for_each_entry(lkb, &ls->ls_lkbtbl[bucket].list, lkb_idtbl_list) { 631 - if (lkb->lkb_id == lkid) 632 - return lkb; 633 - } 634 - return NULL; 635 - } 636 - 637 622 static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret) 638 623 { 639 624 struct dlm_lkb *lkb; 640 - uint16_t bucket = (lkid >> 16); 641 625 642 - if (bucket >= ls->ls_lkbtbl_size) 643 - return -EBADSLT; 644 - 645 - read_lock(&ls->ls_lkbtbl[bucket].lock); 646 - lkb = __find_lkb(ls, lkid); 626 + spin_lock(&ls->ls_lkbidr_spin); 627 + lkb = idr_find(&ls->ls_lkbidr, lkid); 647 628 if (lkb) 648 629 kref_get(&lkb->lkb_ref); 649 - read_unlock(&ls->ls_lkbtbl[bucket].lock); 630 + spin_unlock(&ls->ls_lkbidr_spin); 650 631 651 632 *lkb_ret = lkb; 652 633 return lkb ? 0 : -ENOENT; ··· 647 668 648 669 static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb) 649 670 { 650 - uint16_t bucket = (lkb->lkb_id >> 16); 671 + uint32_t lkid = lkb->lkb_id; 651 672 652 - write_lock(&ls->ls_lkbtbl[bucket].lock); 673 + spin_lock(&ls->ls_lkbidr_spin); 653 674 if (kref_put(&lkb->lkb_ref, kill_lkb)) { 654 - list_del(&lkb->lkb_idtbl_list); 655 - write_unlock(&ls->ls_lkbtbl[bucket].lock); 675 + idr_remove(&ls->ls_lkbidr, lkid); 676 + spin_unlock(&ls->ls_lkbidr_spin); 656 677 657 678 detach_lkb(lkb); 658 679 ··· 662 683 dlm_free_lkb(lkb); 663 684 return 1; 664 685 } else { 665 - write_unlock(&ls->ls_lkbtbl[bucket].lock); 686 + spin_unlock(&ls->ls_lkbidr_spin); 666 687 return 0; 667 688 } 668 689 }
+51 -59
fs/dlm/lockspace.c
··· 472 472 spin_lock_init(&ls->ls_rsbtbl[i].lock); 473 473 } 474 474 475 - size = dlm_config.ci_lkbtbl_size; 476 - ls->ls_lkbtbl_size = size; 477 - 478 - ls->ls_lkbtbl = vmalloc(sizeof(struct dlm_lkbtable) * size); 479 - if (!ls->ls_lkbtbl) 480 - goto out_rsbfree; 481 - for (i = 0; i < size; i++) { 482 - INIT_LIST_HEAD(&ls->ls_lkbtbl[i].list); 483 - rwlock_init(&ls->ls_lkbtbl[i].lock); 484 - ls->ls_lkbtbl[i].counter = 1; 485 - } 475 + idr_init(&ls->ls_lkbidr); 476 + spin_lock_init(&ls->ls_lkbidr_spin); 486 477 487 478 size = dlm_config.ci_dirtbl_size; 488 479 ls->ls_dirtbl_size = size; ··· 596 605 out_dirfree: 597 606 vfree(ls->ls_dirtbl); 598 607 out_lkbfree: 599 - vfree(ls->ls_lkbtbl); 600 - out_rsbfree: 608 + idr_destroy(&ls->ls_lkbidr); 601 609 vfree(ls->ls_rsbtbl); 602 610 out_lsfree: 603 611 if (do_unreg) ··· 631 641 return error; 632 642 } 633 643 634 - /* Return 1 if the lockspace still has active remote locks, 635 - * 2 if the lockspace still has active local locks. 636 - */ 637 - static int lockspace_busy(struct dlm_ls *ls) 644 + static int lkb_idr_is_local(int id, void *p, void *data) 638 645 { 639 - int i, lkb_found = 0; 640 - struct dlm_lkb *lkb; 646 + struct dlm_lkb *lkb = p; 641 647 642 - /* NOTE: We check the lockidtbl here rather than the resource table. 643 - This is because there may be LKBs queued as ASTs that have been 644 - unlinked from their RSBs and are pending deletion once the AST has 645 - been delivered */ 648 + if (!lkb->lkb_nodeid) 649 + return 1; 650 + return 0; 651 + } 646 652 647 - for (i = 0; i < ls->ls_lkbtbl_size; i++) { 648 - read_lock(&ls->ls_lkbtbl[i].lock); 649 - if (!list_empty(&ls->ls_lkbtbl[i].list)) { 650 - lkb_found = 1; 651 - list_for_each_entry(lkb, &ls->ls_lkbtbl[i].list, 652 - lkb_idtbl_list) { 653 - if (!lkb->lkb_nodeid) { 654 - read_unlock(&ls->ls_lkbtbl[i].lock); 655 - return 2; 656 - } 657 - } 658 - } 659 - read_unlock(&ls->ls_lkbtbl[i].lock); 653 + static int lkb_idr_is_any(int id, void *p, void *data) 654 + { 655 + return 1; 656 + } 657 + 658 + static int lkb_idr_free(int id, void *p, void *data) 659 + { 660 + struct dlm_lkb *lkb = p; 661 + 662 + dlm_del_ast(lkb); 663 + 664 + if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY) 665 + dlm_free_lvb(lkb->lkb_lvbptr); 666 + 667 + dlm_free_lkb(lkb); 668 + return 0; 669 + } 670 + 671 + /* NOTE: We check the lkbidr here rather than the resource table. 672 + This is because there may be LKBs queued as ASTs that have been unlinked 673 + from their RSBs and are pending deletion once the AST has been delivered */ 674 + 675 + static int lockspace_busy(struct dlm_ls *ls, int force) 676 + { 677 + int rv; 678 + 679 + spin_lock(&ls->ls_lkbidr_spin); 680 + if (force == 0) { 681 + rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls); 682 + } else if (force == 1) { 683 + rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls); 684 + } else { 685 + rv = 0; 660 686 } 661 - return lkb_found; 687 + spin_unlock(&ls->ls_lkbidr_spin); 688 + return rv; 662 689 } 663 690 664 691 static int release_lockspace(struct dlm_ls *ls, int force) 665 692 { 666 - struct dlm_lkb *lkb; 667 693 struct dlm_rsb *rsb; 668 694 struct list_head *head; 669 695 int i, busy, rv; 670 696 671 - busy = lockspace_busy(ls); 697 + busy = lockspace_busy(ls, force); 672 698 673 699 spin_lock(&lslist_lock); 674 700 if (ls->ls_create_count == 1) { 675 - if (busy > force) 701 + if (busy) { 676 702 rv = -EBUSY; 677 - else { 703 + } else { 678 704 /* remove_lockspace takes ls off lslist */ 679 705 ls->ls_create_count = 0; 680 706 rv = 0; ··· 730 724 vfree(ls->ls_dirtbl); 731 725 732 726 /* 733 - * Free all lkb's on lkbtbl[] lists. 727 + * Free all lkb's in idr 734 728 */ 735 729 736 - for (i = 0; i < ls->ls_lkbtbl_size; i++) { 737 - head = &ls->ls_lkbtbl[i].list; 738 - while (!list_empty(head)) { 739 - lkb = list_entry(head->next, struct dlm_lkb, 740 - lkb_idtbl_list); 730 + idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls); 731 + idr_remove_all(&ls->ls_lkbidr); 732 + idr_destroy(&ls->ls_lkbidr); 741 733 742 - list_del(&lkb->lkb_idtbl_list); 743 - 744 - dlm_del_ast(lkb); 745 - 746 - if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY) 747 - dlm_free_lvb(lkb->lkb_lvbptr); 748 - 749 - dlm_free_lkb(lkb); 750 - } 751 - } 752 734 dlm_astd_resume(); 753 - 754 - vfree(ls->ls_lkbtbl); 755 735 756 736 /* 757 737 * Free all rsb's on rsbtbl[] lists