diff options
Diffstat (limited to 'fs/ocfs2/cluster/heartbeat.c')
-rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 979113479c66..e331f4cb2c81 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -1665,7 +1665,56 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc, | |||
1665 | } | 1665 | } |
1666 | EXPORT_SYMBOL_GPL(o2hb_setup_callback); | 1666 | EXPORT_SYMBOL_GPL(o2hb_setup_callback); |
1667 | 1667 | ||
1668 | int o2hb_register_callback(struct o2hb_callback_func *hc) | 1668 | static struct o2hb_region *o2hb_find_region(const char *region_uuid) |
1669 | { | ||
1670 | struct o2hb_region *p, *reg = NULL; | ||
1671 | |||
1672 | assert_spin_locked(&o2hb_live_lock); | ||
1673 | |||
1674 | list_for_each_entry(p, &o2hb_all_regions, hr_all_item) { | ||
1675 | if (!strcmp(region_uuid, config_item_name(&p->hr_item))) { | ||
1676 | reg = p; | ||
1677 | break; | ||
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | return reg; | ||
1682 | } | ||
1683 | |||
1684 | static int o2hb_region_get(const char *region_uuid) | ||
1685 | { | ||
1686 | int ret = 0; | ||
1687 | struct o2hb_region *reg; | ||
1688 | |||
1689 | spin_lock(&o2hb_live_lock); | ||
1690 | |||
1691 | reg = o2hb_find_region(region_uuid); | ||
1692 | if (!reg) | ||
1693 | ret = -ENOENT; | ||
1694 | spin_unlock(&o2hb_live_lock); | ||
1695 | |||
1696 | if (!ret) | ||
1697 | ret = o2nm_depend_item(®->hr_item); | ||
1698 | |||
1699 | return ret; | ||
1700 | } | ||
1701 | |||
1702 | static void o2hb_region_put(const char *region_uuid) | ||
1703 | { | ||
1704 | struct o2hb_region *reg; | ||
1705 | |||
1706 | spin_lock(&o2hb_live_lock); | ||
1707 | |||
1708 | reg = o2hb_find_region(region_uuid); | ||
1709 | |||
1710 | spin_unlock(&o2hb_live_lock); | ||
1711 | |||
1712 | if (reg) | ||
1713 | o2nm_undepend_item(®->hr_item); | ||
1714 | } | ||
1715 | |||
1716 | int o2hb_register_callback(const char *region_uuid, | ||
1717 | struct o2hb_callback_func *hc) | ||
1669 | { | 1718 | { |
1670 | struct o2hb_callback_func *tmp; | 1719 | struct o2hb_callback_func *tmp; |
1671 | struct list_head *iter; | 1720 | struct list_head *iter; |
@@ -1681,6 +1730,12 @@ int o2hb_register_callback(struct o2hb_callback_func *hc) | |||
1681 | goto out; | 1730 | goto out; |
1682 | } | 1731 | } |
1683 | 1732 | ||
1733 | if (region_uuid) { | ||
1734 | ret = o2hb_region_get(region_uuid); | ||
1735 | if (ret) | ||
1736 | goto out; | ||
1737 | } | ||
1738 | |||
1684 | down_write(&o2hb_callback_sem); | 1739 | down_write(&o2hb_callback_sem); |
1685 | 1740 | ||
1686 | list_for_each(iter, &hbcall->list) { | 1741 | list_for_each(iter, &hbcall->list) { |
@@ -1702,16 +1757,21 @@ out: | |||
1702 | } | 1757 | } |
1703 | EXPORT_SYMBOL_GPL(o2hb_register_callback); | 1758 | EXPORT_SYMBOL_GPL(o2hb_register_callback); |
1704 | 1759 | ||
1705 | void o2hb_unregister_callback(struct o2hb_callback_func *hc) | 1760 | void o2hb_unregister_callback(const char *region_uuid, |
1761 | struct o2hb_callback_func *hc) | ||
1706 | { | 1762 | { |
1707 | BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); | 1763 | BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); |
1708 | 1764 | ||
1709 | mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n", | 1765 | mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n", |
1710 | __builtin_return_address(0), hc); | 1766 | __builtin_return_address(0), hc); |
1711 | 1767 | ||
1768 | /* XXX Can this happen _with_ a region reference? */ | ||
1712 | if (list_empty(&hc->hc_item)) | 1769 | if (list_empty(&hc->hc_item)) |
1713 | return; | 1770 | return; |
1714 | 1771 | ||
1772 | if (region_uuid) | ||
1773 | o2hb_region_put(region_uuid); | ||
1774 | |||
1715 | down_write(&o2hb_callback_sem); | 1775 | down_write(&o2hb_callback_sem); |
1716 | 1776 | ||
1717 | list_del_init(&hc->hc_item); | 1777 | list_del_init(&hc->hc_item); |