📄 nodemanager.c
字号:
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * Copyright (C) 2004, 2005 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */#include <linux/kernel.h>#include <linux/module.h>#include <linux/sysctl.h>#include <linux/configfs.h>#include "endian.h"#include "tcp.h"#include "nodemanager.h"#include "heartbeat.h"#include "masklog.h"#include "sys.h"#include "ver.h"/* for now we operate under the assertion that there can be only one * cluster active at a time. Changing this will require trickling * cluster references throughout where nodes are looked up */static struct o2nm_cluster *o2nm_single_cluster = NULL;#define OCFS2_MAX_HB_CTL_PATH 256static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";static ctl_table ocfs2_nm_table[] = { { .ctl_name = 1, .procname = "hb_ctl_path", .data = ocfs2_hb_ctl_path, .maxlen = OCFS2_MAX_HB_CTL_PATH, .mode = 0644, .proc_handler = &proc_dostring, .strategy = &sysctl_string, }, { .ctl_name = 0 }};static ctl_table ocfs2_mod_table[] = { { .ctl_name = KERN_OCFS2_NM, .procname = "nm", .data = NULL, .maxlen = 0, .mode = 0555, .child = ocfs2_nm_table }, { .ctl_name = 0}};static ctl_table ocfs2_kern_table[] = { { .ctl_name = KERN_OCFS2, .procname = "ocfs2", .data = NULL, .maxlen = 0, .mode = 0555, .child = ocfs2_mod_table }, { .ctl_name = 0}};static ctl_table ocfs2_root_table[] = { { .ctl_name = CTL_FS, .procname = "fs", .data = NULL, .maxlen = 0, .mode = 0555, .child = ocfs2_kern_table }, { .ctl_name = 0 }};static struct ctl_table_header *ocfs2_table_header = NULL;const char *o2nm_get_hb_ctl_path(void){ return ocfs2_hb_ctl_path;}EXPORT_SYMBOL_GPL(o2nm_get_hb_ctl_path);struct o2nm_cluster { struct config_group cl_group; unsigned cl_has_local:1; u8 cl_local_node; rwlock_t cl_nodes_lock; struct o2nm_node *cl_nodes[O2NM_MAX_NODES]; struct rb_root cl_node_ip_tree; /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */ unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];};struct o2nm_node *o2nm_get_node_by_num(u8 node_num){ struct o2nm_node *node = NULL; if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL) goto out; read_lock(&o2nm_single_cluster->cl_nodes_lock); node = o2nm_single_cluster->cl_nodes[node_num]; if (node) config_item_get(&node->nd_item); read_unlock(&o2nm_single_cluster->cl_nodes_lock);out: return node;}EXPORT_SYMBOL_GPL(o2nm_get_node_by_num);int o2nm_configured_node_map(unsigned long *map, unsigned bytes){ struct o2nm_cluster *cluster = o2nm_single_cluster; BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap))); if (cluster == NULL) return -EINVAL; read_lock(&cluster->cl_nodes_lock); memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap)); read_unlock(&cluster->cl_nodes_lock); return 0;}EXPORT_SYMBOL_GPL(o2nm_configured_node_map);static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster, __be32 ip_needle, struct rb_node ***ret_p, struct rb_node **ret_parent){ struct rb_node **p = &cluster->cl_node_ip_tree.rb_node; struct rb_node *parent = NULL; struct o2nm_node *node, *ret = NULL; while (*p) { parent = *p; node = rb_entry(parent, struct o2nm_node, nd_ip_node); if (memcmp(&ip_needle, &node->nd_ipv4_address, sizeof(ip_needle)) < 0) p = &(*p)->rb_left; else if (memcmp(&ip_needle, &node->nd_ipv4_address, sizeof(ip_needle)) > 0) p = &(*p)->rb_right; else { ret = node; break; } } if (ret_p != NULL) *ret_p = p; if (ret_parent != NULL) *ret_parent = parent; return ret;}struct o2nm_node *o2nm_get_node_by_ip(__be32 addr){ struct o2nm_node *node = NULL; struct o2nm_cluster *cluster = o2nm_single_cluster; if (cluster == NULL) goto out; read_lock(&cluster->cl_nodes_lock); node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL); if (node) config_item_get(&node->nd_item); read_unlock(&cluster->cl_nodes_lock);out: return node;}EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip);void o2nm_node_put(struct o2nm_node *node){ config_item_put(&node->nd_item);}EXPORT_SYMBOL_GPL(o2nm_node_put);void o2nm_node_get(struct o2nm_node *node){ config_item_get(&node->nd_item);}EXPORT_SYMBOL_GPL(o2nm_node_get);u8 o2nm_this_node(void){ u8 node_num = O2NM_MAX_NODES; if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local) node_num = o2nm_single_cluster->cl_local_node; return node_num;}EXPORT_SYMBOL_GPL(o2nm_this_node);/* node configfs bits */static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item){ return item ? container_of(to_config_group(item), struct o2nm_cluster, cl_group) : NULL;}static struct o2nm_node *to_o2nm_node(struct config_item *item){ return item ? container_of(item, struct o2nm_node, nd_item) : NULL;}static void o2nm_node_release(struct config_item *item){ struct o2nm_node *node = to_o2nm_node(item); kfree(node);}static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page){ return sprintf(page, "%d\n", node->nd_num);}static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node){ /* through the first node_set .parent * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent);}enum { O2NM_NODE_ATTR_NUM = 0, O2NM_NODE_ATTR_PORT, O2NM_NODE_ATTR_ADDRESS, O2NM_NODE_ATTR_LOCAL,};static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, size_t count){ struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); unsigned long tmp; char *p = (char *)page; tmp = simple_strtoul(p, &p, 0); if (!p || (*p && (*p != '\n'))) return -EINVAL; if (tmp >= O2NM_MAX_NODES) return -ERANGE; /* once we're in the cl_nodes tree networking can look us up by * node number and try to use our address and port attributes * to connect to this node.. make sure that they've been set * before writing the node attribute? */ if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) return -EINVAL; /* XXX */ write_lock(&cluster->cl_nodes_lock); if (cluster->cl_nodes[tmp]) p = NULL; else { cluster->cl_nodes[tmp] = node; node->nd_num = tmp; set_bit(tmp, cluster->cl_nodes_bitmap); } write_unlock(&cluster->cl_nodes_lock); if (p == NULL) return -EEXIST; return count;}static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page){ return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port));}static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node, const char *page, size_t count){ unsigned long tmp; char *p = (char *)page; tmp = simple_strtoul(p, &p, 0); if (!p || (*p && (*p != '\n'))) return -EINVAL; if (tmp == 0) return -EINVAL; if (tmp >= (u16)-1) return -ERANGE; node->nd_ipv4_port = htons(tmp); return count;}static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page){ return sprintf(page, "%u.%u.%u.%u\n", NIPQUAD(node->nd_ipv4_address));}static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node, const char *page, size_t count){ struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); int ret, i; struct rb_node **p, *parent; unsigned int octets[4]; __be32 ipv4_addr = 0; ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2], &octets[1], &octets[0]); if (ret != 4) return -EINVAL; for (i = 0; i < ARRAY_SIZE(octets); i++) { if (octets[i] > 255) return -ERANGE; be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); } ret = 0; write_lock(&cluster->cl_nodes_lock); if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) ret = -EEXIST; else { rb_link_node(&node->nd_ip_node, parent, p); rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); } write_unlock(&cluster->cl_nodes_lock); if (ret) return ret; memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr)); return count;}static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page){ return sprintf(page, "%d\n", node->nd_local);}static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page, size_t count){ struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); unsigned long tmp; char *p = (char *)page; ssize_t ret; tmp = simple_strtoul(p, &p, 0); if (!p || (*p && (*p != '\n'))) return -EINVAL; tmp = !!tmp; /* boolean of whether this node wants to be local */ /* setting local turns on networking rx for now so we require having * set everything else first */ if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) || !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) return -EINVAL; /* XXX */ /* the only failure case is trying to set a new local node * when a different one is already set */ if (tmp && tmp == cluster->cl_has_local && cluster->cl_local_node != node->nd_num) return -EBUSY; /* bring up the rx thread if we're setting the new local node. */ if (tmp && !cluster->cl_has_local) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -