📄 heartbeat.c
字号:
.ca_name = "blocks", .ca_mode = S_IRUGO | S_IWUSR }, .show = o2hb_region_blocks_read, .store = o2hb_region_blocks_write,};static struct o2hb_region_attribute o2hb_region_attr_dev = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "dev", .ca_mode = S_IRUGO | S_IWUSR }, .show = o2hb_region_dev_read, .store = o2hb_region_dev_write,};static struct o2hb_region_attribute o2hb_region_attr_pid = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "pid", .ca_mode = S_IRUGO | S_IRUSR }, .show = o2hb_region_pid_read,};static struct configfs_attribute *o2hb_region_attrs[] = { &o2hb_region_attr_block_bytes.attr, &o2hb_region_attr_start_block.attr, &o2hb_region_attr_blocks.attr, &o2hb_region_attr_dev.attr, &o2hb_region_attr_pid.attr, NULL,};static ssize_t o2hb_region_show(struct config_item *item, struct configfs_attribute *attr, char *page){ struct o2hb_region *reg = to_o2hb_region(item); struct o2hb_region_attribute *o2hb_region_attr = container_of(attr, struct o2hb_region_attribute, attr); ssize_t ret = 0; if (o2hb_region_attr->show) ret = o2hb_region_attr->show(reg, page); return ret;}static ssize_t o2hb_region_store(struct config_item *item, struct configfs_attribute *attr, const char *page, size_t count){ struct o2hb_region *reg = to_o2hb_region(item); struct o2hb_region_attribute *o2hb_region_attr = container_of(attr, struct o2hb_region_attribute, attr); ssize_t ret = -EINVAL; if (o2hb_region_attr->store) ret = o2hb_region_attr->store(reg, page, count); return ret;}static struct configfs_item_operations o2hb_region_item_ops = { .release = o2hb_region_release, .show_attribute = o2hb_region_show, .store_attribute = o2hb_region_store,};static struct config_item_type o2hb_region_type = { .ct_item_ops = &o2hb_region_item_ops, .ct_attrs = o2hb_region_attrs, .ct_owner = THIS_MODULE,};/* heartbeat set */struct o2hb_heartbeat_group { struct config_group hs_group; /* some stuff? */};static struct o2hb_heartbeat_group *to_o2hb_heartbeat_group(struct config_group *group){ return group ? container_of(group, struct o2hb_heartbeat_group, hs_group) : NULL;}static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group, const char *name){ struct o2hb_region *reg = NULL; struct config_item *ret = NULL; reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); if (reg == NULL) goto out; /* ENOMEM */ config_item_init_type_name(®->hr_item, name, &o2hb_region_type); ret = ®->hr_item; spin_lock(&o2hb_live_lock); list_add_tail(®->hr_all_item, &o2hb_all_regions); spin_unlock(&o2hb_live_lock);out: if (ret == NULL) kfree(reg); return ret;}static void o2hb_heartbeat_group_drop_item(struct config_group *group, struct config_item *item){ struct task_struct *hb_task; struct o2hb_region *reg = to_o2hb_region(item); /* stop the thread when the user removes the region dir */ spin_lock(&o2hb_live_lock); hb_task = reg->hr_task; reg->hr_task = NULL; spin_unlock(&o2hb_live_lock); if (hb_task) kthread_stop(hb_task); /* * If we're racing a dev_write(), we need to wake them. They will * check reg->hr_task */ if (atomic_read(®->hr_steady_iterations) != 0) { atomic_set(®->hr_steady_iterations, 0); wake_up(&o2hb_steady_queue); } config_item_put(item);}struct o2hb_heartbeat_group_attribute { struct configfs_attribute attr; ssize_t (*show)(struct o2hb_heartbeat_group *, char *); ssize_t (*store)(struct o2hb_heartbeat_group *, const char *, size_t);};static ssize_t o2hb_heartbeat_group_show(struct config_item *item, struct configfs_attribute *attr, char *page){ struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item)); struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr = container_of(attr, struct o2hb_heartbeat_group_attribute, attr); ssize_t ret = 0; if (o2hb_heartbeat_group_attr->show) ret = o2hb_heartbeat_group_attr->show(reg, page); return ret;}static ssize_t o2hb_heartbeat_group_store(struct config_item *item, struct configfs_attribute *attr, const char *page, size_t count){ struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item)); struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr = container_of(attr, struct o2hb_heartbeat_group_attribute, attr); ssize_t ret = -EINVAL; if (o2hb_heartbeat_group_attr->store) ret = o2hb_heartbeat_group_attr->store(reg, page, count); return ret;}static ssize_t o2hb_heartbeat_group_threshold_show(struct o2hb_heartbeat_group *group, char *page){ return sprintf(page, "%u\n", o2hb_dead_threshold);}static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group *group, const char *page, size_t count){ unsigned long tmp; char *p = (char *)page; tmp = simple_strtoul(p, &p, 10); if (!p || (*p && (*p != '\n'))) return -EINVAL; /* this will validate ranges for us. */ o2hb_dead_threshold_set((unsigned int) tmp); return count;}static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "dead_threshold", .ca_mode = S_IRUGO | S_IWUSR }, .show = o2hb_heartbeat_group_threshold_show, .store = o2hb_heartbeat_group_threshold_store,};static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = { &o2hb_heartbeat_group_attr_threshold.attr, NULL,};static struct configfs_item_operations o2hb_hearbeat_group_item_ops = { .show_attribute = o2hb_heartbeat_group_show, .store_attribute = o2hb_heartbeat_group_store,};static struct configfs_group_operations o2hb_heartbeat_group_group_ops = { .make_item = o2hb_heartbeat_group_make_item, .drop_item = o2hb_heartbeat_group_drop_item,};static struct config_item_type o2hb_heartbeat_group_type = { .ct_group_ops = &o2hb_heartbeat_group_group_ops, .ct_item_ops = &o2hb_hearbeat_group_item_ops, .ct_attrs = o2hb_heartbeat_group_attrs, .ct_owner = THIS_MODULE,};/* this is just here to avoid touching group in heartbeat.h which the * entire damn world #includes */struct config_group *o2hb_alloc_hb_set(void){ struct o2hb_heartbeat_group *hs = NULL; struct config_group *ret = NULL; hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL); if (hs == NULL) goto out; config_group_init_type_name(&hs->hs_group, "heartbeat", &o2hb_heartbeat_group_type); ret = &hs->hs_group;out: if (ret == NULL) kfree(hs); return ret;}void o2hb_free_hb_set(struct config_group *group){ struct o2hb_heartbeat_group *hs = to_o2hb_heartbeat_group(group); kfree(hs);}/* hb callback registration and issueing */static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type){ if (type == O2HB_NUM_CB) return ERR_PTR(-EINVAL); return &o2hb_callbacks[type];}void o2hb_setup_callback(struct o2hb_callback_func *hc, enum o2hb_callback_type type, o2hb_cb_func *func, void *data, int priority){ INIT_LIST_HEAD(&hc->hc_item); hc->hc_func = func; hc->hc_data = data; hc->hc_priority = priority; hc->hc_type = type; hc->hc_magic = O2HB_CB_MAGIC;}EXPORT_SYMBOL_GPL(o2hb_setup_callback);static struct o2hb_region *o2hb_find_region(const char *region_uuid){ struct o2hb_region *p, *reg = NULL; assert_spin_locked(&o2hb_live_lock); list_for_each_entry(p, &o2hb_all_regions, hr_all_item) { if (!strcmp(region_uuid, config_item_name(&p->hr_item))) { reg = p; break; } } return reg;}static int o2hb_region_get(const char *region_uuid){ int ret = 0; struct o2hb_region *reg; spin_lock(&o2hb_live_lock); reg = o2hb_find_region(region_uuid); if (!reg) ret = -ENOENT; spin_unlock(&o2hb_live_lock); if (ret) goto out; ret = o2nm_depend_this_node(); if (ret) goto out; ret = o2nm_depend_item(®->hr_item); if (ret) o2nm_undepend_this_node();out: return ret;}static void o2hb_region_put(const char *region_uuid){ struct o2hb_region *reg; spin_lock(&o2hb_live_lock); reg = o2hb_find_region(region_uuid); spin_unlock(&o2hb_live_lock); if (reg) { o2nm_undepend_item(®->hr_item); o2nm_undepend_this_node(); }}int o2hb_register_callback(const char *region_uuid, struct o2hb_callback_func *hc){ struct o2hb_callback_func *tmp; struct list_head *iter; struct o2hb_callback *hbcall; int ret; BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); BUG_ON(!list_empty(&hc->hc_item)); hbcall = hbcall_from_type(hc->hc_type); if (IS_ERR(hbcall)) { ret = PTR_ERR(hbcall); goto out; } if (region_uuid) { ret = o2hb_region_get(region_uuid); if (ret) goto out; } down_write(&o2hb_callback_sem); list_for_each(iter, &hbcall->list) { tmp = list_entry(iter, struct o2hb_callback_func, hc_item); if (hc->hc_priority < tmp->hc_priority) { list_add_tail(&hc->hc_item, iter); break; } } if (list_empty(&hc->hc_item)) list_add_tail(&hc->hc_item, &hbcall->list); up_write(&o2hb_callback_sem); ret = 0;out: mlog(ML_HEARTBEAT, "returning %d on behalf of %p for funcs %p\n", ret, __builtin_return_address(0), hc); return ret;}EXPORT_SYMBOL_GPL(o2hb_register_callback);void o2hb_unregister_callback(const char *region_uuid, struct o2hb_callback_func *hc){ BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n", __builtin_return_address(0), hc); /* XXX Can this happen _with_ a region reference? */ if (list_empty(&hc->hc_item)) return; if (region_uuid) o2hb_region_put(region_uuid); down_write(&o2hb_callback_sem); list_del_init(&hc->hc_item); up_write(&o2hb_callback_sem);}EXPORT_SYMBOL_GPL(o2hb_unregister_callback);int o2hb_check_node_heartbeating(u8 node_num){ unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; o2hb_fill_node_map(testing_map, sizeof(testing_map)); if (!test_bit(node_num, testing_map)) { mlog(ML_HEARTBEAT, "node (%u) does not have heartbeating enabled.\n", node_num); return 0; } return 1;}EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating);int o2hb_check_node_heartbeating_from_callback(u8 node_num){ unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; o2hb_fill_node_map_from_callback(testing_map, sizeof(testing_map)); if (!test_bit(node_num, testing_map)) { mlog(ML_HEARTBEAT, "node (%u) does not have heartbeating enabled.\n", node_num); return 0; } return 1;}EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating_from_callback);/* Makes sure our local node is configured with a node number, and is * heartbeating. */int o2hb_check_local_node_heartbeating(void){ u8 node_num; /* if this node was set then we have networking */ node_num = o2nm_this_node(); if (node_num == O2NM_MAX_NODES) { mlog(ML_HEARTBEAT, "this node has not been configured.\n"); return 0; } return o2hb_check_node_heartbeating(node_num);}EXPORT_SYMBOL_GPL(o2hb_check_local_node_heartbeating);/* * this is just a hack until we get the plumbing which flips file systems * read only and drops the hb ref instead of killing the node dead. */void o2hb_stop_all_regions(void){ struct o2hb_region *reg; mlog(ML_ERROR, "stopping heartbeat on all active regions.\n"); spin_lock(&o2hb_live_lock); list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) reg->hr_unclean_stop = 1; spin_unlock(&o2hb_live_lock);}EXPORT_SYMBOL_GPL(o2hb_stop_all_regions);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -