2 /* The userspace cluster heartbeat directory will be populated with symbolic
3 * links to the nodes who are heartbeating in the given group */
5 #include <linux/configfs.h>
8 #include "nodemanager.h"
10 struct o2hb_user_region {
11 struct o2hb_heartbeat_resource hr_res;
12 unsigned long hr_live_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
15 static inline struct o2hb_user_region *to_o2hb_user_region(struct o2hb_heartbeat_resource *hbres)
17 return container_of(hbres, struct o2hb_user_region, hr_res);
20 static inline struct o2hb_user_region *item_to_o2hb_user_region(struct config_item *item)
22 return to_o2hb_user_region(to_o2hb_heartbeat_resource(item));
25 static inline void o2hb_user_region_get(struct o2hb_user_region *region)
27 o2hb_heartbeat_resource_get(®ion->hr_res);
30 static inline void o2hb_user_region_put(struct o2hb_user_region *region)
32 o2hb_heartbeat_resource_put(®ion->hr_res);
34 static int o2hb_user_group_allow_link(struct config_item *src,
35 struct config_item *target)
37 struct o2nm_node *node = to_o2nm_node(target);
38 struct o2hb_user_region *hbr = item_to_o2hb_user_region(src);
40 struct o2hb_node_event event = {
41 .hn_item = LIST_HEAD_INIT(event.hn_item),
42 .hn_res = &hbr->hr_res,
45 /* Make sure the target is within the same cluster */
46 if (src->ci_parent->ci_parent != target->ci_parent->ci_parent)
49 printk ("Node %s is up in group %s\n", target->ci_name, src->ci_name);
51 spin_lock(&o2hb_live_lock);
52 set_bit(node->nd_num, hbr->hr_live_bitmap);
54 /* also add a link back to the node */
56 /* Notify listeners that this node is up */
57 o2hb_queue_node_event(&event, O2HB_NODE_UP_CB, node, node->nd_num);
58 spin_unlock(&o2hb_live_lock);
60 o2hb_run_event_list (&event);
65 static int o2hb_user_group_drop_link(struct config_item *src,
66 struct config_item *target)
68 struct o2nm_node *node = to_o2nm_node(target);
69 struct o2hb_user_region *hbr = item_to_o2hb_user_region(src);
71 struct o2hb_node_event event = {
72 .hn_item = LIST_HEAD_INIT(event.hn_item),
73 .hn_res = &hbr->hr_res,
76 /* Somehow notify listeners that this node is down */
77 printk ("Node %s is down in group %s\n", target->ci_name,
80 spin_lock(&o2hb_live_lock);
81 clear_bit(node->nd_num, hbr->hr_live_bitmap);
83 /* Notify listeners that this node is down */
84 o2hb_queue_node_event (&event, O2HB_NODE_DOWN_CB, node, node->nd_num);
85 spin_unlock(&o2hb_live_lock);
87 o2hb_run_event_list (&event);
92 static struct configfs_item_operations o2hb_user_region_ops = {
93 .allow_link = o2hb_user_group_allow_link,
94 .drop_link = o2hb_user_group_drop_link,
97 struct config_item_type o2hb_user_region_type = {
98 .ct_item_ops = &o2hb_user_region_ops,
99 .ct_owner = THIS_MODULE,
102 /* How to create a heartbeat region */
103 static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group,
106 struct o2hb_user_region *region;
107 struct config_item *ret = NULL;
109 region = kzalloc(sizeof (*region), GFP_KERNEL);
113 /* mkdir <fs uuid> */
114 config_item_init_type_name(®ion->hr_res.hr_item, name,
115 &o2hb_user_region_type);
117 ret = ®ion->hr_res.hr_item;
125 /* How to remove a heartbeat region */
126 static void o2hb_heartbeat_group_drop_item(struct config_group *group,
127 struct config_item *item)
129 config_item_put (item);
132 static struct configfs_group_operations o2hb_user_heartbeat_root_ops = {
133 .make_item = o2hb_heartbeat_group_make_item,
134 .drop_item = o2hb_heartbeat_group_drop_item,
137 static inline struct o2hb_user_region *o2hb_user_region_get_by_name(const char *resource)
139 struct o2hb_heartbeat_resource *hbr;
140 struct o2hb_user_region *region = NULL;
142 hbr = o2hb_heartbeat_resource_get_by_name(resource);
144 region = to_o2hb_user_region(hbr);
149 static int o2hb_user_fill_node_map(const char *resource, unsigned long *map,
152 struct o2hb_user_region *region;
153 if (resource == NULL)
156 if (len > BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof (*map))
159 region = o2hb_user_region_get_by_name(resource);
163 memcpy (map, region->hr_live_bitmap, len);
165 o2hb_user_region_put(region);
170 static int o2hb_user_check_node_status(const char *resource, u8 node_num)
175 struct o2hb_user_region *region;
176 region = o2hb_user_region_get_by_name(resource);
180 ret = test_bit(node_num, region->hr_live_bitmap);
181 o2hb_user_region_put(region);
183 struct o2nm_node *node = o2nm_get_node_by_num(node_num);
184 ret = (node && atomic_read(&node->nd_count));
190 static struct o2hb_heartbeat_group user_heartbeat_group = {
192 .ct_group_ops = &o2hb_user_heartbeat_root_ops,
193 .ct_owner = THIS_MODULE,
196 .fill_node_map = o2hb_user_fill_node_map,
197 .check_node_status = o2hb_user_check_node_status,
200 static int __init o2hb_user_heartbeat_init(void)
202 return o2hb_register_heartbeat_group(&user_heartbeat_group);
205 static void __exit o2hb_user_heartbeat_exit(void)
207 o2hb_unregister_heartbeat_group(&user_heartbeat_group);
210 MODULE_AUTHOR("Novell");
211 MODULE_LICENSE("GPL");
213 module_init(o2hb_user_heartbeat_init);
214 module_exit(o2hb_user_heartbeat_exit);