diff options
Diffstat (limited to 'fs/ocfs2/dlm/dlmdomain.c')
-rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 3b179d6cbde0..6ed6b95dcf93 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -132,10 +132,12 @@ static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); | |||
132 | * New in version 1.1: | 132 | * New in version 1.1: |
133 | * - Message DLM_QUERY_REGION added to support global heartbeat | 133 | * - Message DLM_QUERY_REGION added to support global heartbeat |
134 | * - Message DLM_QUERY_NODEINFO added to allow online node removes | 134 | * - Message DLM_QUERY_NODEINFO added to allow online node removes |
135 | * New in version 1.2: | ||
136 | * - Message DLM_BEGIN_EXIT_DOMAIN_MSG added to mark start of exit domain | ||
135 | */ | 137 | */ |
136 | static const struct dlm_protocol_version dlm_protocol = { | 138 | static const struct dlm_protocol_version dlm_protocol = { |
137 | .pv_major = 1, | 139 | .pv_major = 1, |
138 | .pv_minor = 1, | 140 | .pv_minor = 2, |
139 | }; | 141 | }; |
140 | 142 | ||
141 | #define DLM_DOMAIN_BACKOFF_MS 200 | 143 | #define DLM_DOMAIN_BACKOFF_MS 200 |
@@ -449,14 +451,18 @@ redo_bucket: | |||
449 | dropped = dlm_empty_lockres(dlm, res); | 451 | dropped = dlm_empty_lockres(dlm, res); |
450 | 452 | ||
451 | spin_lock(&res->spinlock); | 453 | spin_lock(&res->spinlock); |
452 | __dlm_lockres_calc_usage(dlm, res); | 454 | if (dropped) |
453 | iter = res->hash_node.next; | 455 | __dlm_lockres_calc_usage(dlm, res); |
456 | else | ||
457 | iter = res->hash_node.next; | ||
454 | spin_unlock(&res->spinlock); | 458 | spin_unlock(&res->spinlock); |
455 | 459 | ||
456 | dlm_lockres_put(res); | 460 | dlm_lockres_put(res); |
457 | 461 | ||
458 | if (dropped) | 462 | if (dropped) { |
463 | cond_resched_lock(&dlm->spinlock); | ||
459 | goto redo_bucket; | 464 | goto redo_bucket; |
465 | } | ||
460 | } | 466 | } |
461 | cond_resched_lock(&dlm->spinlock); | 467 | cond_resched_lock(&dlm->spinlock); |
462 | num += n; | 468 | num += n; |
@@ -486,6 +492,28 @@ static int dlm_no_joining_node(struct dlm_ctxt *dlm) | |||
486 | return ret; | 492 | return ret; |
487 | } | 493 | } |
488 | 494 | ||
495 | static int dlm_begin_exit_domain_handler(struct o2net_msg *msg, u32 len, | ||
496 | void *data, void **ret_data) | ||
497 | { | ||
498 | struct dlm_ctxt *dlm = data; | ||
499 | unsigned int node; | ||
500 | struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf; | ||
501 | |||
502 | if (!dlm_grab(dlm)) | ||
503 | return 0; | ||
504 | |||
505 | node = exit_msg->node_idx; | ||
506 | mlog(0, "%s: Node %u sent a begin exit domain message\n", dlm->name, node); | ||
507 | |||
508 | spin_lock(&dlm->spinlock); | ||
509 | set_bit(node, dlm->exit_domain_map); | ||
510 | spin_unlock(&dlm->spinlock); | ||
511 | |||
512 | dlm_put(dlm); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
489 | static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm) | 517 | static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm) |
490 | { | 518 | { |
491 | /* Yikes, a double spinlock! I need domain_lock for the dlm | 519 | /* Yikes, a double spinlock! I need domain_lock for the dlm |
@@ -542,6 +570,7 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, | |||
542 | 570 | ||
543 | spin_lock(&dlm->spinlock); | 571 | spin_lock(&dlm->spinlock); |
544 | clear_bit(node, dlm->domain_map); | 572 | clear_bit(node, dlm->domain_map); |
573 | clear_bit(node, dlm->exit_domain_map); | ||
545 | __dlm_print_nodes(dlm); | 574 | __dlm_print_nodes(dlm); |
546 | 575 | ||
547 | /* notify anything attached to the heartbeat events */ | 576 | /* notify anything attached to the heartbeat events */ |
@@ -554,29 +583,56 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, | |||
554 | return 0; | 583 | return 0; |
555 | } | 584 | } |
556 | 585 | ||
557 | static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, | 586 | static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, u32 msg_type, |
558 | unsigned int node) | 587 | unsigned int node) |
559 | { | 588 | { |
560 | int status; | 589 | int status; |
561 | struct dlm_exit_domain leave_msg; | 590 | struct dlm_exit_domain leave_msg; |
562 | 591 | ||
563 | mlog(0, "Asking node %u if we can leave the domain %s me = %u\n", | 592 | mlog(0, "%s: Sending domain exit message %u to node %u\n", dlm->name, |
564 | node, dlm->name, dlm->node_num); | 593 | msg_type, node); |
565 | 594 | ||
566 | memset(&leave_msg, 0, sizeof(leave_msg)); | 595 | memset(&leave_msg, 0, sizeof(leave_msg)); |
567 | leave_msg.node_idx = dlm->node_num; | 596 | leave_msg.node_idx = dlm->node_num; |
568 | 597 | ||
569 | status = o2net_send_message(DLM_EXIT_DOMAIN_MSG, dlm->key, | 598 | status = o2net_send_message(msg_type, dlm->key, &leave_msg, |
570 | &leave_msg, sizeof(leave_msg), node, | 599 | sizeof(leave_msg), node, NULL); |
571 | NULL); | ||
572 | if (status < 0) | 600 | if (status < 0) |
573 | mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to " | 601 | mlog(ML_ERROR, "Error %d sending domain exit message %u " |
574 | "node %u\n", status, DLM_EXIT_DOMAIN_MSG, dlm->key, node); | 602 | "to node %u on domain %s\n", status, msg_type, node, |
575 | mlog(0, "status return %d from o2net_send_message\n", status); | 603 | dlm->name); |
576 | 604 | ||
577 | return status; | 605 | return status; |
578 | } | 606 | } |
579 | 607 | ||
608 | static void dlm_begin_exit_domain(struct dlm_ctxt *dlm) | ||
609 | { | ||
610 | int node = -1; | ||
611 | |||
612 | /* Support for begin exit domain was added in 1.2 */ | ||
613 | if (dlm->dlm_locking_proto.pv_major == 1 && | ||
614 | dlm->dlm_locking_proto.pv_minor < 2) | ||
615 | return; | ||
616 | |||
617 | /* | ||
618 | * Unlike DLM_EXIT_DOMAIN_MSG, DLM_BEGIN_EXIT_DOMAIN_MSG is purely | ||
619 | * informational. Meaning if a node does not receive the message, | ||
620 | * so be it. | ||
621 | */ | ||
622 | spin_lock(&dlm->spinlock); | ||
623 | while (1) { | ||
624 | node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES, node + 1); | ||
625 | if (node >= O2NM_MAX_NODES) | ||
626 | break; | ||
627 | if (node == dlm->node_num) | ||
628 | continue; | ||
629 | |||
630 | spin_unlock(&dlm->spinlock); | ||
631 | dlm_send_one_domain_exit(dlm, DLM_BEGIN_EXIT_DOMAIN_MSG, node); | ||
632 | spin_lock(&dlm->spinlock); | ||
633 | } | ||
634 | spin_unlock(&dlm->spinlock); | ||
635 | } | ||
580 | 636 | ||
581 | static void dlm_leave_domain(struct dlm_ctxt *dlm) | 637 | static void dlm_leave_domain(struct dlm_ctxt *dlm) |
582 | { | 638 | { |
@@ -602,7 +658,8 @@ static void dlm_leave_domain(struct dlm_ctxt *dlm) | |||
602 | 658 | ||
603 | clear_node = 1; | 659 | clear_node = 1; |
604 | 660 | ||
605 | status = dlm_send_one_domain_exit(dlm, node); | 661 | status = dlm_send_one_domain_exit(dlm, DLM_EXIT_DOMAIN_MSG, |
662 | node); | ||
606 | if (status < 0 && | 663 | if (status < 0 && |
607 | status != -ENOPROTOOPT && | 664 | status != -ENOPROTOOPT && |
608 | status != -ENOTCONN) { | 665 | status != -ENOTCONN) { |
@@ -677,6 +734,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) | |||
677 | 734 | ||
678 | if (leave) { | 735 | if (leave) { |
679 | mlog(0, "shutting down domain %s\n", dlm->name); | 736 | mlog(0, "shutting down domain %s\n", dlm->name); |
737 | dlm_begin_exit_domain(dlm); | ||
680 | 738 | ||
681 | /* We changed dlm state, notify the thread */ | 739 | /* We changed dlm state, notify the thread */ |
682 | dlm_kick_thread(dlm, NULL); | 740 | dlm_kick_thread(dlm, NULL); |
@@ -909,6 +967,7 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, | |||
909 | * leftover join state. */ | 967 | * leftover join state. */ |
910 | BUG_ON(dlm->joining_node != assert->node_idx); | 968 | BUG_ON(dlm->joining_node != assert->node_idx); |
911 | set_bit(assert->node_idx, dlm->domain_map); | 969 | set_bit(assert->node_idx, dlm->domain_map); |
970 | clear_bit(assert->node_idx, dlm->exit_domain_map); | ||
912 | __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); | 971 | __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); |
913 | 972 | ||
914 | printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n", | 973 | printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n", |
@@ -1793,6 +1852,13 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm) | |||
1793 | if (status) | 1852 | if (status) |
1794 | goto bail; | 1853 | goto bail; |
1795 | 1854 | ||
1855 | status = o2net_register_handler(DLM_BEGIN_EXIT_DOMAIN_MSG, dlm->key, | ||
1856 | sizeof(struct dlm_exit_domain), | ||
1857 | dlm_begin_exit_domain_handler, | ||
1858 | dlm, NULL, &dlm->dlm_domain_handlers); | ||
1859 | if (status) | ||
1860 | goto bail; | ||
1861 | |||
1796 | bail: | 1862 | bail: |
1797 | if (status) | 1863 | if (status) |
1798 | dlm_unregister_domain_handlers(dlm); | 1864 | dlm_unregister_domain_handlers(dlm); |