nodemanager.c revision f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950
10c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel/* -*- mode: c; c-basic-offset: 8; -*-
20c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * vim: noexpandtab sw=8 ts=8 sts=0:
30c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel *
40c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * Copyright (C) 2004, 2005 Oracle.  All rights reserved.
50c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel *
60c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * This program is free software; you can redistribute it and/or
70c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * modify it under the terms of the GNU General Public
80c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * License as published by the Free Software Foundation; either
90c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * version 2 of the License, or (at your option) any later version.
100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel *
110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * This program is distributed in the hope that it will be useful,
120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * but WITHOUT ANY WARRANTY; without even the implied warranty of
130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * General Public License for more details.
150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel *
160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * You should have received a copy of the GNU General Public
170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * License along with this program; if not, write to the
180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * Boston, MA 021110-1307, USA.
200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel */
210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include <linux/kernel.h>
230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include <linux/module.h>
240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include <linux/configfs.h>
250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include "tcp.h"
270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include "nodemanager.h"
280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include "heartbeat.h"
290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include "masklog.h"
300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include "sys.h"
310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#include "ver.h"
320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel/* for now we operate under the assertion that there can be only one
340c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * cluster active at a time.  Changing this will require trickling
350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel * cluster references throughout where nodes are looked up */
36296b75ed6a3b35f613961cefe4962ce1cf586d77Andrew Beekhofstruct o2nm_cluster *o2nm_single_cluster = NULL;
370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstruct o2nm_node *o2nm_get_node_by_num(u8 node_num)
400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = NULL;
420c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
430c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL)
440c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out;
450c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
460c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	read_lock(&o2nm_single_cluster->cl_nodes_lock);
470c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	node = o2nm_single_cluster->cl_nodes[node_num];
480c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (node)
490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		config_item_get(&node->nd_item);
500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	read_unlock(&o2nm_single_cluster->cl_nodes_lock);
510c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout:
520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return node;
530c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
540c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelEXPORT_SYMBOL_GPL(o2nm_get_node_by_num);
550c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
560c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelint o2nm_configured_node_map(unsigned long *map, unsigned bytes)
570c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
580c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = o2nm_single_cluster;
590c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap)));
610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
620c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (cluster == NULL)
630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL;
640c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
650c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	read_lock(&cluster->cl_nodes_lock);
660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap));
670c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	read_unlock(&cluster->cl_nodes_lock);
680c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return 0;
700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
710c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelEXPORT_SYMBOL_GPL(o2nm_configured_node_map);
720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster,
740c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel						  __be32 ip_needle,
750c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel						  struct rb_node ***ret_p,
760c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel						  struct rb_node **ret_parent)
770c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
780c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct rb_node **p = &cluster->cl_node_ip_tree.rb_node;
790c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct rb_node *parent = NULL;
800c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node, *ret = NULL;
810c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	while (*p) {
8379cd22d3ac921b9209bf813c7e75e6b69e74896cAkinobu Mita		int cmp;
8479cd22d3ac921b9209bf813c7e75e6b69e74896cAkinobu Mita
850c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		parent = *p;
860c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		node = rb_entry(parent, struct o2nm_node, nd_ip_node);
870c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8879cd22d3ac921b9209bf813c7e75e6b69e74896cAkinobu Mita		cmp = memcmp(&ip_needle, &node->nd_ipv4_address,
8979cd22d3ac921b9209bf813c7e75e6b69e74896cAkinobu Mita				sizeof(ip_needle));
9079cd22d3ac921b9209bf813c7e75e6b69e74896cAkinobu Mita		if (cmp < 0)
910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			p = &(*p)->rb_left;
9279cd22d3ac921b9209bf813c7e75e6b69e74896cAkinobu Mita		else if (cmp > 0)
930c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			p = &(*p)->rb_right;
940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		else {
950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			ret = node;
960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			break;
970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		}
980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
990c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1000c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret_p != NULL)
1010c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		*ret_p = p;
1020c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret_parent != NULL)
1030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		*ret_parent = parent;
1040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return ret;
1060c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstruct o2nm_node *o2nm_get_node_by_ip(__be32 addr)
1090c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = NULL;
1110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = o2nm_single_cluster;
1120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (cluster == NULL)
1140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out;
1150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	read_lock(&cluster->cl_nodes_lock);
1170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL);
1180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (node)
1190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		config_item_get(&node->nd_item);
1200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	read_unlock(&cluster->cl_nodes_lock);
1210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout:
1230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return node;
1240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelEXPORT_SYMBOL_GPL(o2nm_get_node_by_ip);
1260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelvoid o2nm_node_put(struct o2nm_node *node)
1280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_item_put(&node->nd_item);
1300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelEXPORT_SYMBOL_GPL(o2nm_node_put);
1320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelvoid o2nm_node_get(struct o2nm_node *node)
1340c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_item_get(&node->nd_item);
1360c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelEXPORT_SYMBOL_GPL(o2nm_node_get);
1380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelu8 o2nm_this_node(void)
1400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	u8 node_num = O2NM_MAX_NODES;
1420c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1430c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local)
1440c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		node_num = o2nm_single_cluster->cl_local_node;
1450c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1460c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return node_num;
1470c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1480c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelEXPORT_SYMBOL_GPL(o2nm_this_node);
1490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel/* node configfs bits */
1510c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_cluster *to_o2nm_cluster(struct config_item *item)
1530c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1540c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return item ?
1550c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		container_of(to_config_group(item), struct o2nm_cluster,
1560c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			     cl_group)
1570c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		: NULL;
1580c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1590c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node *to_o2nm_node(struct config_item *item)
1610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1620c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return item ? container_of(item, struct o2nm_node, nd_item) : NULL;
1630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1640c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1650c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic void o2nm_node_release(struct config_item *item)
1660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1670c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = to_o2nm_node(item);
1680c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	kfree(node);
1690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1710c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page)
1720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return sprintf(page, "%d\n", node->nd_num);
1740c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1750c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1760c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node)
1770c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1780c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* through the first node_set .parent
1790c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */
1800c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent);
1810c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
1820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1830c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelenum {
1840c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	O2NM_NODE_ATTR_NUM = 0,
1850c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	O2NM_NODE_ATTR_PORT,
1860c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	O2NM_NODE_ATTR_ADDRESS,
1870c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	O2NM_NODE_ATTR_LOCAL,
1880c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
1890c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1900c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
1910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				   size_t count)
1920c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
1930c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
1940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	unsigned long tmp;
1950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	char *p = (char *)page;
1960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
1970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	tmp = simple_strtoul(p, &p, 0);
1980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!p || (*p && (*p != '\n')))
1990c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL;
2000c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2010c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (tmp >= O2NM_MAX_NODES)
2020c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -ERANGE;
2030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* once we're in the cl_nodes tree networking can look us up by
2050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * node number and try to use our address and port attributes
2060c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * to connect to this node.. make sure that they've been set
2070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * before writing the node attribute? */
2080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
2090c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
2100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL; /* XXX */
2110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	write_lock(&cluster->cl_nodes_lock);
2130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (cluster->cl_nodes[tmp])
2140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		p = NULL;
2150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	else  {
2160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_nodes[tmp] = node;
2170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		node->nd_num = tmp;
2180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		set_bit(tmp, cluster->cl_nodes_bitmap);
2190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
2200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	write_unlock(&cluster->cl_nodes_lock);
2210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (p == NULL)
2220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EEXIST;
2230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return count;
2250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
2260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page)
2270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
2280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port));
2290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
2300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node,
2320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel					 const char *page, size_t count)
2330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
2340c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	unsigned long tmp;
2350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	char *p = (char *)page;
2360c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	tmp = simple_strtoul(p, &p, 0);
2380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!p || (*p && (*p != '\n')))
2390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL;
2400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (tmp == 0)
2420c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL;
2430c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (tmp >= (u16)-1)
2440c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -ERANGE;
2450c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2460c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	node->nd_ipv4_port = htons(tmp);
2470c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2480c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return count;
2490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
2500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2510c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page)
2520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
2530c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return sprintf(page, "%u.%u.%u.%u\n", NIPQUAD(node->nd_ipv4_address));
2540c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
2550c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2560c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
2570c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel					    const char *page,
2580c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel					    size_t count)
2590c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
2600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
2610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	int ret, i;
2620c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct rb_node **p, *parent;
2630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	unsigned int octets[4];
2640c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	__be32 ipv4_addr = 0;
2650c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2],
2670c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		     &octets[1], &octets[0]);
2680c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret != 4)
2690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL;
2700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2710c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	for (i = 0; i < ARRAY_SIZE(octets); i++) {
2720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		if (octets[i] > 255)
2730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			return -ERANGE;
2740c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		be32_add_cpu(&ipv4_addr, octets[i] << (i * 8));
2750c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
2760c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2770c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ret = 0;
2780c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	write_lock(&cluster->cl_nodes_lock);
2790c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
2800c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		ret = -EEXIST;
2810c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	else {
2820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		rb_link_node(&node->nd_ip_node, parent, p);
2830c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
2840c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
2850c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	write_unlock(&cluster->cl_nodes_lock);
2860c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret)
2870c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return ret;
2880c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2890c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr));
2900c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return count;
2920c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
2930c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page)
2950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
2960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return sprintf(page, "%d\n", node->nd_local);
2970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
2980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
2990c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page,
3000c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				     size_t count)
3010c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
3020c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
3030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	unsigned long tmp;
3040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	char *p = (char *)page;
3050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ssize_t ret;
3060c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	tmp = simple_strtoul(p, &p, 0);
3080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!p || (*p && (*p != '\n')))
3090c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL;
3100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	tmp = !!tmp; /* boolean of whether this node wants to be local */
3120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* setting local turns on networking rx for now so we require having
3140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * set everything else first */
3150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
3160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	    !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) ||
3170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
3180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EINVAL; /* XXX */
3190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* the only failure case is trying to set a new local node
3210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * when a different one is already set */
3220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (tmp && tmp == cluster->cl_has_local &&
3230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	    cluster->cl_local_node != node->nd_num)
3240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EBUSY;
3250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* bring up the rx thread if we're setting the new local node. */
3270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (tmp && !cluster->cl_has_local) {
3280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		ret = o2net_start_listening(node);
3290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		if (ret)
3300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			return ret;
3310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
3320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!tmp && cluster->cl_has_local &&
3340c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	    cluster->cl_local_node == node->nd_num) {
3350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		o2net_stop_listening(node);
3360c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
3370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
3380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	node->nd_local = tmp;
3400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (node->nd_local) {
3410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_has_local = tmp;
3420c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_local_node = node->nd_num;
3430c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
3440c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3450c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return count;
3460c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
3470c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3480c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstruct o2nm_node_attribute {
3490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct configfs_attribute attr;
3500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ssize_t (*show)(struct o2nm_node *, char *);
3510c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ssize_t (*store)(struct o2nm_node *, const char *, size_t);
3520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
3530c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3540c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node_attribute o2nm_node_attr_num = {
3550c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.attr	= { .ca_owner = THIS_MODULE,
3560c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_name = "num",
3570c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_mode = S_IRUGO | S_IWUSR },
3580c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.show	= o2nm_node_num_read,
3590c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.store	= o2nm_node_num_write,
3600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
3610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3620c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node_attribute o2nm_node_attr_ipv4_port = {
3630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.attr	= { .ca_owner = THIS_MODULE,
3640c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_name = "ipv4_port",
3650c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_mode = S_IRUGO | S_IWUSR },
3660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.show	= o2nm_node_ipv4_port_read,
3670c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.store	= o2nm_node_ipv4_port_write,
3680c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
3690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node_attribute o2nm_node_attr_ipv4_address = {
3710c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.attr	= { .ca_owner = THIS_MODULE,
3720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_name = "ipv4_address",
3730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_mode = S_IRUGO | S_IWUSR },
3740c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.show	= o2nm_node_ipv4_address_read,
3750c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.store	= o2nm_node_ipv4_address_write,
3760c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
3770c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3780c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node_attribute o2nm_node_attr_local = {
3790c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.attr	= { .ca_owner = THIS_MODULE,
3800c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_name = "local",
3810c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		    .ca_mode = S_IRUGO | S_IWUSR },
3820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.show	= o2nm_node_local_read,
3830c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.store	= o2nm_node_local_write,
3840c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
3850c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3860c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct configfs_attribute *o2nm_node_attrs[] = {
3870c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	[O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr,
3880c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	[O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr,
3890c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	[O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr,
3900c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	[O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr,
3910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	NULL,
3920c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
3930c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
3940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic int o2nm_attr_index(struct configfs_attribute *attr)
3950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
3960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	int i;
3970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) {
3980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		if (attr == o2nm_node_attrs[i])
3990c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			return i;
4000c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
4010c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	BUG();
4020c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return 0;
4030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
4040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_show(struct config_item *item,
4060c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			      struct configfs_attribute *attr,
4070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			      char *page)
4080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
4090c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = to_o2nm_node(item);
4100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node_attribute *o2nm_node_attr =
4110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		container_of(attr, struct o2nm_node_attribute, attr);
4120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ssize_t ret = 0;
4130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (o2nm_node_attr->show)
4150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		ret = o2nm_node_attr->show(node, page);
4160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return ret;
4170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
4180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic ssize_t o2nm_node_store(struct config_item *item,
4200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			       struct configfs_attribute *attr,
4210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			       const char *page, size_t count)
4220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
4230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = to_o2nm_node(item);
4240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node_attribute *o2nm_node_attr =
4250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		container_of(attr, struct o2nm_node_attribute, attr);
4260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ssize_t ret;
4270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	int attr_index = o2nm_attr_index(attr);
4280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (o2nm_node_attr->store == NULL) {
4300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		ret = -EINVAL;
4310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out;
4320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
4330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4340c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (test_bit(attr_index, &node->nd_set_attributes))
4350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		return -EBUSY;
4360c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ret = o2nm_node_attr->store(node, page, count);
4380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret < count)
4390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out;
4400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	set_bit(attr_index, &node->nd_set_attributes);
4420c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout:
4430c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return ret;
4440c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
4450c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4460c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct configfs_item_operations o2nm_node_item_ops = {
4470c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.release		= o2nm_node_release,
4480c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.show_attribute		= o2nm_node_show,
4490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.store_attribute	= o2nm_node_store,
4500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
4510c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct config_item_type o2nm_node_type = {
4530c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_item_ops	= &o2nm_node_item_ops,
4540c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_attrs	= o2nm_node_attrs,
4550c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_owner	= THIS_MODULE,
4560c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
4570c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4580c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel/* node set */
4590c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstruct o2nm_node_group {
4610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct config_group ns_group;
4620c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* some stuff? */
4630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
4640c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
4650c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#if 0
4660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
4670c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
4680c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return group ?
4690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		container_of(group, struct o2nm_node_group, ns_group)
4700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		: NULL;
4710c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
4720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#endif
4730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
474b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystruct o2nm_cluster_attribute {
475b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct configfs_attribute attr;
476b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ssize_t (*show)(struct o2nm_cluster *, char *);
477b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ssize_t (*store)(struct o2nm_cluster *, const char *, size_t);
478b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney};
479b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
480b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
481b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney                                       unsigned int *val)
482b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
483b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	unsigned long tmp;
484b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	char *p = (char *)page;
485b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
486b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	tmp = simple_strtoul(p, &p, 0);
487b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (!p || (*p && (*p != '\n')))
488b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		return -EINVAL;
489b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
490b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (tmp == 0)
491b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		return -EINVAL;
492b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (tmp >= (u32)-1)
493b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		return -ERANGE;
494b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
495b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	*val = tmp;
496b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
497b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return count;
498b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
499b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
500b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_idle_timeout_ms_read(
501b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster, char *page)
502b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
503b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return sprintf(page, "%u\n", cluster->cl_idle_timeout_ms);
504b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
505b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
506b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_idle_timeout_ms_write(
507b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster, const char *page, size_t count)
508b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
509b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ssize_t ret;
510b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	unsigned int val;
511b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
512b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ret =  o2nm_cluster_attr_write(page, count, &val);
513b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
514b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (ret > 0) {
515828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		if (cluster->cl_idle_timeout_ms != val
516828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			&& o2net_num_connected_peers()) {
517828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			mlog(ML_NOTICE,
518828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     "o2net: cannot change idle timeout after "
519828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     "the first peer has agreed to it."
520828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     "  %d connected peers\n",
521828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     o2net_num_connected_peers());
522828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			ret = -EINVAL;
523828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		} else if (val <= cluster->cl_keepalive_delay_ms) {
524b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney			mlog(ML_NOTICE, "o2net: idle timeout must be larger "
525b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney			     "than keepalive delay\n");
526828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			ret = -EINVAL;
527828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		} else {
528828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			cluster->cl_idle_timeout_ms = val;
529b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		}
530b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	}
531b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
532b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return ret;
533b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
534b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
535b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_keepalive_delay_ms_read(
536b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster, char *page)
537b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
538b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return sprintf(page, "%u\n", cluster->cl_keepalive_delay_ms);
539b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
540b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
541b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_keepalive_delay_ms_write(
542b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster, const char *page, size_t count)
543b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
544b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ssize_t ret;
545b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	unsigned int val;
546b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
547b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ret =  o2nm_cluster_attr_write(page, count, &val);
548b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
549b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (ret > 0) {
550828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		if (cluster->cl_keepalive_delay_ms != val
551828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		    && o2net_num_connected_peers()) {
552828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			mlog(ML_NOTICE,
553828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     "o2net: cannot change keepalive delay after"
554828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     " the first peer has agreed to it."
555828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     "  %d connected peers\n",
556828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			     o2net_num_connected_peers());
557828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			ret = -EINVAL;
558828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		} else if (val >= cluster->cl_idle_timeout_ms) {
559b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney			mlog(ML_NOTICE, "o2net: keepalive delay must be "
560b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney			     "smaller than idle timeout\n");
561828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			ret = -EINVAL;
562828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof		} else {
563828ae6afbef03bfe107a4a8cc38798419d6a2765Andrew Beekhof			cluster->cl_keepalive_delay_ms = val;
564b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		}
565b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	}
566b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
567b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return ret;
568b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
569b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
570b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_reconnect_delay_ms_read(
571b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster, char *page)
572b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
573b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return sprintf(page, "%u\n", cluster->cl_reconnect_delay_ms);
574b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
575b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
576b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_attr_reconnect_delay_ms_write(
577b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster, const char *page, size_t count)
578b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
579b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return o2nm_cluster_attr_write(page, count,
580b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	                               &cluster->cl_reconnect_delay_ms);
581b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
582b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic struct o2nm_cluster_attribute o2nm_cluster_attr_idle_timeout_ms = {
583b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.attr	= { .ca_owner = THIS_MODULE,
584b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		    .ca_name = "idle_timeout_ms",
585b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		    .ca_mode = S_IRUGO | S_IWUSR },
586b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.show	= o2nm_cluster_attr_idle_timeout_ms_read,
587b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.store	= o2nm_cluster_attr_idle_timeout_ms_write,
588b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney};
589b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
590b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic struct o2nm_cluster_attribute o2nm_cluster_attr_keepalive_delay_ms = {
591b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.attr	= { .ca_owner = THIS_MODULE,
592b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		    .ca_name = "keepalive_delay_ms",
593b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		    .ca_mode = S_IRUGO | S_IWUSR },
594b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.show	= o2nm_cluster_attr_keepalive_delay_ms_read,
595b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.store	= o2nm_cluster_attr_keepalive_delay_ms_write,
596b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney};
597b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
598b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic struct o2nm_cluster_attribute o2nm_cluster_attr_reconnect_delay_ms = {
599b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.attr	= { .ca_owner = THIS_MODULE,
600b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		    .ca_name = "reconnect_delay_ms",
601b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		    .ca_mode = S_IRUGO | S_IWUSR },
602b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.show	= o2nm_cluster_attr_reconnect_delay_ms_read,
603b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.store	= o2nm_cluster_attr_reconnect_delay_ms_write,
604b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney};
605b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
606b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic struct configfs_attribute *o2nm_cluster_attrs[] = {
607b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	&o2nm_cluster_attr_idle_timeout_ms.attr,
608b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	&o2nm_cluster_attr_keepalive_delay_ms.attr,
609b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	&o2nm_cluster_attr_reconnect_delay_ms.attr,
610b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	NULL,
611b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney};
612b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_show(struct config_item *item,
613b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney                                 struct configfs_attribute *attr,
614b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney                                 char *page)
615b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
616b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
617b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster_attribute *o2nm_cluster_attr =
618b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		container_of(attr, struct o2nm_cluster_attribute, attr);
619b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ssize_t ret = 0;
620b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
621b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (o2nm_cluster_attr->show)
622b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		ret = o2nm_cluster_attr->show(cluster, page);
623b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return ret;
624b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
625b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
626b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneystatic ssize_t o2nm_cluster_store(struct config_item *item,
627b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney                                  struct configfs_attribute *attr,
628b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney                                  const char *page, size_t count)
629b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney{
630b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
631b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	struct o2nm_cluster_attribute *o2nm_cluster_attr =
632b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		container_of(attr, struct o2nm_cluster_attribute, attr);
633b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ssize_t ret;
634b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
635b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (o2nm_cluster_attr->store == NULL) {
636b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		ret = -EINVAL;
637b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		goto out;
638b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	}
639b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
640b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	ret = o2nm_cluster_attr->store(cluster, page, count);
641b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	if (ret < count)
642b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney		goto out;
643b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoneyout:
644b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	return ret;
645b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney}
646b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney
647f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Beckerstatic struct config_item *o2nm_node_group_make_item(struct config_group *group,
648f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker						     const char *name)
6490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
6500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = NULL;
651f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	struct config_item *ret = NULL;
6520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
653f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	if (strlen(name) > O2NM_MAX_NAME_LEN)
654f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker		goto out; /* ENAMETOOLONG */
6550c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
656cd86128088554d64fea1679191509f00e6353c5bRobert P. J. Day	node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
657f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	if (node == NULL)
658f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker		goto out; /* ENOMEM */
6590c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
6610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
6620c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	spin_lock_init(&node->nd_lock);
6630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
664f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	ret = &node->nd_item;
6650c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout:
667f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	if (ret == NULL)
6680c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		kfree(node);
6690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return ret;
6710c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
6720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic void o2nm_node_group_drop_item(struct config_group *group,
6740c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				      struct config_item *item)
6750c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
6760c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node *node = to_o2nm_node(item);
6770c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent);
6780c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6790c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2net_disconnect_node(node);
6800c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6810c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (cluster->cl_has_local &&
6820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	    (cluster->cl_local_node == node->nd_num)) {
6830c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_has_local = 0;
6840c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
6850c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		o2net_stop_listening(node);
6860c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
6870c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6880c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* XXX call into net to stop this node from trading messages */
6890c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6900c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	write_lock(&cluster->cl_nodes_lock);
6910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6920c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* XXX sloppy */
6930c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (node->nd_ipv4_address)
6940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree);
6950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
6960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* nd_num might be 0 if the node number hasn't been set.. */
6970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (cluster->cl_nodes[node->nd_num] == node) {
6980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_nodes[node->nd_num] = NULL;
6990c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		clear_bit(node->nd_num, cluster->cl_nodes_bitmap);
7000c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
7010c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	write_unlock(&cluster->cl_nodes_lock);
7020c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_item_put(item);
7040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
7050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7060c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct configfs_group_operations o2nm_node_group_group_ops = {
7070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.make_item	= o2nm_node_group_make_item,
7080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.drop_item	= o2nm_node_group_drop_item,
7090c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
7100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct config_item_type o2nm_node_group_type = {
7120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_group_ops	= &o2nm_node_group_group_ops,
7130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_owner	= THIS_MODULE,
7140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
7150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel/* cluster */
7170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic void o2nm_cluster_release(struct config_item *item)
7190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
7200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
7210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	kfree(cluster->cl_group.default_groups);
7230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	kfree(cluster);
7240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
7250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct configfs_item_operations o2nm_cluster_item_ops = {
7270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.release	= o2nm_cluster_release,
728b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.show_attribute		= o2nm_cluster_show,
729b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.store_attribute	= o2nm_cluster_store,
7300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
7310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct config_item_type o2nm_cluster_type = {
7330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_item_ops	= &o2nm_cluster_item_ops,
734b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	.ct_attrs	= o2nm_cluster_attrs,
7350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_owner	= THIS_MODULE,
7360c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
7370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel/* cluster set */
7390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstruct o2nm_cluster_group {
7410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct configfs_subsystem cs_subsys;
7420c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* some stuff? */
7430c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
7440c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7450c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#if 0
7460c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group)
7470c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
7480c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return group ?
7490c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys)
7500c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	       : NULL;
7510c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
7520c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel#endif
7530c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
754f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Beckerstatic struct config_group *o2nm_cluster_group_make_group(struct config_group *group,
755f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker							  const char *name)
7560c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
7570c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = NULL;
7580c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_node_group *ns = NULL;
759f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	struct config_group *o2hb_group = NULL, *ret = NULL;
7600c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	void *defs = NULL;
7610c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7621b1dcc1b57a49136f118a0f16367256ff9994a69Jes Sorensen	/* this runs under the parent dir's i_mutex; there can be only
7630c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	 * one caller in here at a time */
764f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	if (o2nm_single_cluster)
765f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker		goto out; /* ENOSPC */
7660c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
767cd86128088554d64fea1679191509f00e6353c5bRobert P. J. Day	cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
768cd86128088554d64fea1679191509f00e6353c5bRobert P. J. Day	ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
7690c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
7700c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2hb_group = o2hb_alloc_hb_set();
771f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL)
7720c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out;
7730c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7740c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_group_init_type_name(&cluster->cl_group, name,
7750c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				    &o2nm_cluster_type);
7760c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_group_init_type_name(&ns->ns_group, "node",
7770c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				    &o2nm_node_group_type);
7780c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7790c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	cluster->cl_group.default_groups = defs;
7800c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	cluster->cl_group.default_groups[0] = &ns->ns_group;
7810c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	cluster->cl_group.default_groups[1] = o2hb_group;
7820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	cluster->cl_group.default_groups[2] = NULL;
7830c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	rwlock_init(&cluster->cl_nodes_lock);
7840c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	cluster->cl_node_ip_tree = RB_ROOT;
785b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT;
786b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	cluster->cl_idle_timeout_ms    = O2NET_IDLE_TIMEOUT_MS_DEFAULT;
787b5dd80304da482d77b2320e1a01a189e656b9770Jeff Mahoney	cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT;
7880c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
789f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	ret = &cluster->cl_group;
7900c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2nm_single_cluster = cluster;
7910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
7920c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout:
793f89ab8619e5320cc9c2576f5f8dcbaf6c0ba3950Joel Becker	if (ret == NULL) {
7940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		kfree(cluster);
7950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		kfree(ns);
7960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		o2hb_free_hb_set(o2hb_group);
7970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		kfree(defs);
7980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
7990c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8000c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return ret;
8010c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
8020c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item)
8040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
8050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
8060c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	int i;
8070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	struct config_item *killme;
8080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8090c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	BUG_ON(o2nm_single_cluster != cluster);
8100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2nm_single_cluster = NULL;
8110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	for (i = 0; cluster->cl_group.default_groups[i]; i++) {
8130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		killme = &cluster->cl_group.default_groups[i]->cg_item;
8140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		cluster->cl_group.default_groups[i] = NULL;
8150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		config_item_put(killme);
8160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
8170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_item_put(item);
8190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
8200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct configfs_group_operations o2nm_cluster_group_group_ops = {
8220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.make_group	= o2nm_cluster_group_make_group,
8230c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.drop_item	= o2nm_cluster_group_drop_item,
8240c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
8250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct config_item_type o2nm_cluster_group_type = {
8270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_group_ops	= &o2nm_cluster_group_group_ops,
8280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.ct_owner	= THIS_MODULE,
8290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
8300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic struct o2nm_cluster_group o2nm_cluster_group = {
8320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	.cs_subsys = {
8330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		.su_group = {
8340c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			.cg_item = {
8350c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				.ci_namebuf = "cluster",
8360c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel				.ci_type = &o2nm_cluster_group_type,
8370c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel			},
8380c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		},
8390c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	},
8400c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel};
8410c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
84214829422be6d6b6721f61b1e749acf5a9cb664d8Joel Beckerint o2nm_depend_item(struct config_item *item)
84314829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker{
84414829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker	return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
84514829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker}
84614829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker
84714829422be6d6b6721f61b1e749acf5a9cb664d8Joel Beckervoid o2nm_undepend_item(struct config_item *item)
84814829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker{
84914829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker	configfs_undepend_item(&o2nm_cluster_group.cs_subsys, item);
85014829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker}
85114829422be6d6b6721f61b1e749acf5a9cb664d8Joel Becker
85216c6a4f24de2933b26477ad5dfb71f518220d641Joel Beckerint o2nm_depend_this_node(void)
85316c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker{
85416c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	int ret = 0;
85516c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	struct o2nm_node *local_node;
85616c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
85716c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	local_node = o2nm_get_node_by_num(o2nm_this_node());
85816c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	if (!local_node) {
85916c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker		ret = -EINVAL;
86016c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker		goto out;
86116c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	}
86216c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
86316c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	ret = o2nm_depend_item(&local_node->nd_item);
86416c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	o2nm_node_put(local_node);
86516c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
86616c6a4f24de2933b26477ad5dfb71f518220d641Joel Beckerout:
86716c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	return ret;
86816c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker}
86916c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
87016c6a4f24de2933b26477ad5dfb71f518220d641Joel Beckervoid o2nm_undepend_this_node(void)
87116c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker{
87216c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	struct o2nm_node *local_node;
87316c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
87416c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	local_node = o2nm_get_node_by_num(o2nm_this_node());
87516c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	BUG_ON(!local_node);
87616c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
87716c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	o2nm_undepend_item(&local_node->nd_item);
87816c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker	o2nm_node_put(local_node);
87916c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker}
88016c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
88116c6a4f24de2933b26477ad5dfb71f518220d641Joel Becker
8820c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic void __exit exit_o2nm(void)
8830c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
8840c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	/* XXX sync with hb callbacks and shut down hb? */
8850c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2net_unregister_hb_callbacks();
8860c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
8870c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2cb_sys_shutdown();
8880c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8890c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2net_exit();
8900c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
8910c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8920c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelstatic int __init init_o2nm(void)
8930c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel{
8940c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	int ret = -1;
8950c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8960c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	cluster_print_version();
8970c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
8980c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2hb_init();
8992309e9e040fe29469fb85a384636c455b62fe525Sunil Mushran
9002309e9e040fe29469fb85a384636c455b62fe525Sunil Mushran	ret = o2net_init();
9012309e9e040fe29469fb85a384636c455b62fe525Sunil Mushran	if (ret)
9022309e9e040fe29469fb85a384636c455b62fe525Sunil Mushran		goto out;
9030c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
9040c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ret = o2net_register_hb_callbacks();
9050c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret)
9063878f110f71a0971ff7acc15dd6db711b6ef37c6Joel Becker		goto out_o2net;
9070c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
9080c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
909e6bd07aee739566803425acdbf5cdb29919164e1Joel Becker	mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex);
9100c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
9110c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (ret) {
9120c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
9130c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out_callbacks;
9140c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	}
9150c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
9160c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	ret = o2cb_sys_init();
9170c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	if (!ret)
9180c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel		goto out;
9190c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
9200c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
9210c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout_callbacks:
9220c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	o2net_unregister_hb_callbacks();
923895928b8380cc697ac56e9732cedf549c0a4f79cJeff Mahoneyout_o2net:
924895928b8380cc697ac56e9732cedf549c0a4f79cJeff Mahoney	o2net_exit();
9250c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelout:
9260c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel	return ret;
9270c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel}
9280c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
9290c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelMODULE_AUTHOR("Oracle");
9300c83ed8eeb28a045cdbd0b216679938aa9e665feKurt HackelMODULE_LICENSE("GPL");
9310c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackel
9320c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelmodule_init(init_o2nm)
9330c83ed8eeb28a045cdbd0b216679938aa9e665feKurt Hackelmodule_exit(exit_o2nm)
934