⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nodemanager.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- 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 + -