📄 heartbeat.c
字号:
if (ret) { mlog_errno(ret); goto out; } ret = o2hb_populate_slot_data(reg); if (ret) { mlog_errno(ret); goto out; } INIT_WORK(®->hr_write_timeout_work, o2hb_write_timeout, reg); /* * A node is considered live after it has beat LIVE_THRESHOLD * times. We're not steady until we've given them a chance * _after_ our first read. */ atomic_set(®->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1); reg->hr_task = kthread_run(o2hb_thread, reg, "o2hb-%s", reg->hr_item.ci_name); if (IS_ERR(reg->hr_task)) { ret = PTR_ERR(reg->hr_task); mlog_errno(ret); reg->hr_task = NULL; goto out; } ret = wait_event_interruptible(o2hb_steady_queue, atomic_read(®->hr_steady_iterations) == 0); if (ret) { kthread_stop(reg->hr_task); reg->hr_task = NULL; goto out; } ret = count;out: if (filp) fput(filp); if (inode) iput(inode); if (ret < 0) { if (reg->hr_bdev) { blkdev_put(reg->hr_bdev); reg->hr_bdev = NULL; } } return ret;}struct o2hb_region_attribute { struct configfs_attribute attr; ssize_t (*show)(struct o2hb_region *, char *); ssize_t (*store)(struct o2hb_region *, const char *, size_t);};static struct o2hb_region_attribute o2hb_region_attr_block_bytes = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "block_bytes", .ca_mode = S_IRUGO | S_IWUSR }, .show = o2hb_region_block_bytes_read, .store = o2hb_region_block_bytes_write,};static struct o2hb_region_attribute o2hb_region_attr_start_block = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "start_block", .ca_mode = S_IRUGO | S_IWUSR }, .show = o2hb_region_start_block_read, .store = o2hb_region_start_block_write,};static struct o2hb_region_attribute o2hb_region_attr_blocks = { .attr = { .ca_owner = THIS_MODULE, .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 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, 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 = kcalloc(1, 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 o2hb_region *reg = to_o2hb_region(item); /* stop the thread when the user removes the region dir */ if (reg->hr_task) { kthread_stop(reg->hr_task); reg->hr_task = NULL; } 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 = kcalloc(1, 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);int o2hb_register_callback(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; } 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);int o2hb_unregister_callback(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); if (list_empty(&hc->hc_item)) return 0; down_write(&o2hb_callback_sem); list_del_init(&hc->hc_item); up_write(&o2hb_callback_sem); return 0;}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 + -