diff options
Diffstat (limited to 'fs/ocfs2/dlm/dlmdomain.c')
-rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 3b179d6cbde0..3aff23feefdc 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 |
@@ -486,6 +488,28 @@ static int dlm_no_joining_node(struct dlm_ctxt *dlm) | |||
486 | return ret; | 488 | return ret; |
487 | } | 489 | } |
488 | 490 | ||
491 | static int dlm_begin_exit_domain_handler(struct o2net_msg *msg, u32 len, | ||
492 | void *data, void **ret_data) | ||
493 | { | ||
494 | struct dlm_ctxt *dlm = data; | ||
495 | unsigned int node; | ||
496 | struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf; | ||
497 | |||
498 | if (!dlm_grab(dlm)) | ||
499 | return 0; | ||
500 | |||
501 | node = exit_msg->node_idx; | ||
502 | mlog(0, "%s: Node %u sent a begin exit domain message\n", dlm->name, node); | ||
503 | |||
504 | spin_lock(&dlm->spinlock); | ||
505 | set_bit(node, dlm->exit_domain_map); | ||
506 | spin_unlock(&dlm->spinlock); | ||
507 | |||
508 | dlm_put(dlm); | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
489 | static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm) | 513 | static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm) |
490 | { | 514 | { |
491 | /* Yikes, a double spinlock! I need domain_lock for the dlm | 515 | /* Yikes, a double spinlock! I need domain_lock for the dlm |
@@ -542,6 +566,7 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, | |||
542 | 566 | ||
543 | spin_lock(&dlm->spinlock); | 567 | spin_lock(&dlm->spinlock); |
544 | clear_bit(node, dlm->domain_map); | 568 | clear_bit(node, dlm->domain_map); |
569 | clear_bit(node, dlm->exit_domain_map); | ||
545 | __dlm_print_nodes(dlm); | 570 | __dlm_print_nodes(dlm); |
546 | 571 | ||
547 | /* notify anything attached to the heartbeat events */ | 572 | /* notify anything attached to the heartbeat events */ |
@@ -554,29 +579,56 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, | |||
554 | return 0; | 579 | return 0; |
555 | } | 580 | } |
556 | 581 | ||
557 | static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, | 582 | static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm, u32 msg_type, |
558 | unsigned int node) | 583 | unsigned int node) |
559 | { | 584 | { |
560 | int status; | 585 | int status; |
561 | struct dlm_exit_domain leave_msg; | 586 | struct dlm_exit_domain leave_msg; |
562 | 587 | ||
563 | mlog(0, "Asking node %u if we can leave the domain %s me = %u\n", | 588 | mlog(0, "%s: Sending domain exit message %u to node %u\n", dlm->name, |
564 | node, dlm->name, dlm->node_num); | 589 | msg_type, node); |
565 | 590 | ||
566 | memset(&leave_msg, 0, sizeof(leave_msg)); | 591 | memset(&leave_msg, 0, sizeof(leave_msg)); |
567 | leave_msg.node_idx = dlm->node_num; | 592 | leave_msg.node_idx = dlm->node_num; |
568 | 593 | ||
569 | status = o2net_send_message(DLM_EXIT_DOMAIN_MSG, dlm->key, | 594 | status = o2net_send_message(msg_type, dlm->key, &leave_msg, |
570 | &leave_msg, sizeof(leave_msg), node, | 595 | sizeof(leave_msg), node, NULL); |
571 | NULL); | ||
572 | if (status < 0) | 596 | if (status < 0) |
573 | mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to " | 597 | mlog(ML_ERROR, "Error %d sending domain exit message %u " |
574 | "node %u\n", status, DLM_EXIT_DOMAIN_MSG, dlm->key, node); | 598 | "to node %u on domain %s\n", status, msg_type, node, |
575 | mlog(0, "status return %d from o2net_send_message\n", status); | 599 | dlm->name); |
576 | 600 | ||
577 | return status; | 601 | return status; |
578 | } | 602 | } |
579 | 603 | ||
604 | static void dlm_begin_exit_domain(struct dlm_ctxt *dlm) | ||
605 | { | ||
606 | int node = -1; | ||
607 | |||
608 | /* Support for begin exit domain was added in 1.2 */ | ||
609 | if (dlm->dlm_locking_proto.pv_major == 1 && | ||
610 | dlm->dlm_locking_proto.pv_minor < 2) | ||
611 | return; | ||
612 | |||
613 | /* | ||
614 | * Unlike DLM_EXIT_DOMAIN_MSG, DLM_BEGIN_EXIT_DOMAIN_MSG is purely | ||
615 | * informational. Meaning if a node does not receive the message, | ||
616 | * so be it. | ||
617 | */ | ||
618 | spin_lock(&dlm->spinlock); | ||
619 | while (1) { | ||
620 | node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES, node + 1); | ||
621 | if (node >= O2NM_MAX_NODES) | ||
622 | break; | ||
623 | if (node == dlm->node_num) | ||
624 | continue; | ||
625 | |||
626 | spin_unlock(&dlm->spinlock); | ||
627 | dlm_send_one_domain_exit(dlm, DLM_BEGIN_EXIT_DOMAIN_MSG, node); | ||
628 | spin_lock(&dlm->spinlock); | ||
629 | } | ||
630 | spin_unlock(&dlm->spinlock); | ||
631 | } | ||
580 | 632 | ||
581 | static void dlm_leave_domain(struct dlm_ctxt *dlm) | 633 | static void dlm_leave_domain(struct dlm_ctxt *dlm) |
582 | { | 634 | { |
@@ -602,7 +654,8 @@ static void dlm_leave_domain(struct dlm_ctxt *dlm) | |||
602 | 654 | ||
603 | clear_node = 1; | 655 | clear_node = 1; |
604 | 656 | ||
605 | status = dlm_send_one_domain_exit(dlm, node); | 657 | status = dlm_send_one_domain_exit(dlm, DLM_EXIT_DOMAIN_MSG, |
658 | node); | ||
606 | if (status < 0 && | 659 | if (status < 0 && |
607 | status != -ENOPROTOOPT && | 660 | status != -ENOPROTOOPT && |
608 | status != -ENOTCONN) { | 661 | status != -ENOTCONN) { |
@@ -677,6 +730,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) | |||
677 | 730 | ||
678 | if (leave) { | 731 | if (leave) { |
679 | mlog(0, "shutting down domain %s\n", dlm->name); | 732 | mlog(0, "shutting down domain %s\n", dlm->name); |
733 | dlm_begin_exit_domain(dlm); | ||
680 | 734 | ||
681 | /* We changed dlm state, notify the thread */ | 735 | /* We changed dlm state, notify the thread */ |
682 | dlm_kick_thread(dlm, NULL); | 736 | dlm_kick_thread(dlm, NULL); |
@@ -909,6 +963,7 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, | |||
909 | * leftover join state. */ | 963 | * leftover join state. */ |
910 | BUG_ON(dlm->joining_node != assert->node_idx); | 964 | BUG_ON(dlm->joining_node != assert->node_idx); |
911 | set_bit(assert->node_idx, dlm->domain_map); | 965 | set_bit(assert->node_idx, dlm->domain_map); |
966 | clear_bit(assert->node_idx, dlm->exit_domain_map); | ||
912 | __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); | 967 | __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); |
913 | 968 | ||
914 | printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n", | 969 | printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n", |
@@ -1793,6 +1848,13 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm) | |||
1793 | if (status) | 1848 | if (status) |
1794 | goto bail; | 1849 | goto bail; |
1795 | 1850 | ||
1851 | status = o2net_register_handler(DLM_BEGIN_EXIT_DOMAIN_MSG, dlm->key, | ||
1852 | sizeof(struct dlm_exit_domain), | ||
1853 | dlm_begin_exit_domain_handler, | ||
1854 | dlm, NULL, &dlm->dlm_domain_handlers); | ||
1855 | if (status) | ||
1856 | goto bail; | ||
1857 | |||
1796 | bail: | 1858 | bail: |
1797 | if (status) | 1859 | if (status) |
1798 | dlm_unregister_domain_handlers(dlm); | 1860 | dlm_unregister_domain_handlers(dlm); |