xref: /openbmc/linux/fs/ocfs2/cluster/nodemanager.c (revision 71dd5d65)
1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fa60ce2cSMasahiro Yamada /*
30c83ed8eSKurt Hackel  * Copyright (C) 2004, 2005 Oracle.  All rights reserved.
40c83ed8eSKurt Hackel  */
50c83ed8eSKurt Hackel 
65a0e3ad6STejun Heo #include <linux/slab.h>
70c83ed8eSKurt Hackel #include <linux/kernel.h>
80c83ed8eSKurt Hackel #include <linux/module.h>
90c83ed8eSKurt Hackel #include <linux/configfs.h>
100c83ed8eSKurt Hackel 
110c83ed8eSKurt Hackel #include "tcp.h"
120c83ed8eSKurt Hackel #include "nodemanager.h"
130c83ed8eSKurt Hackel #include "heartbeat.h"
140c83ed8eSKurt Hackel #include "masklog.h"
150c83ed8eSKurt Hackel #include "sys.h"
160c83ed8eSKurt Hackel 
170c83ed8eSKurt Hackel /* for now we operate under the assertion that there can be only one
180c83ed8eSKurt Hackel  * cluster active at a time.  Changing this will require trickling
190c83ed8eSKurt Hackel  * cluster references throughout where nodes are looked up */
20296b75edSAndrew Beekhof struct o2nm_cluster *o2nm_single_cluster = NULL;
210c83ed8eSKurt Hackel 
22480bd564SColin Ian King static const char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = {
23f6656d26SSunil Mushran 	"reset",	/* O2NM_FENCE_RESET */
24f6656d26SSunil Mushran 	"panic",	/* O2NM_FENCE_PANIC */
25f6656d26SSunil Mushran };
260c83ed8eSKurt Hackel 
27853bc26aSalex chen static inline void o2nm_lock_subsystem(void);
28853bc26aSalex chen static inline void o2nm_unlock_subsystem(void);
29853bc26aSalex chen 
o2nm_get_node_by_num(u8 node_num)300c83ed8eSKurt Hackel struct o2nm_node *o2nm_get_node_by_num(u8 node_num)
310c83ed8eSKurt Hackel {
320c83ed8eSKurt Hackel 	struct o2nm_node *node = NULL;
330c83ed8eSKurt Hackel 
340c83ed8eSKurt Hackel 	if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL)
350c83ed8eSKurt Hackel 		goto out;
360c83ed8eSKurt Hackel 
370c83ed8eSKurt Hackel 	read_lock(&o2nm_single_cluster->cl_nodes_lock);
380c83ed8eSKurt Hackel 	node = o2nm_single_cluster->cl_nodes[node_num];
390c83ed8eSKurt Hackel 	if (node)
400c83ed8eSKurt Hackel 		config_item_get(&node->nd_item);
410c83ed8eSKurt Hackel 	read_unlock(&o2nm_single_cluster->cl_nodes_lock);
420c83ed8eSKurt Hackel out:
430c83ed8eSKurt Hackel 	return node;
440c83ed8eSKurt Hackel }
450c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_node_by_num);
460c83ed8eSKurt Hackel 
o2nm_configured_node_map(unsigned long * map,unsigned bytes)470c83ed8eSKurt Hackel int o2nm_configured_node_map(unsigned long *map, unsigned bytes)
480c83ed8eSKurt Hackel {
490c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = o2nm_single_cluster;
500c83ed8eSKurt Hackel 
510c83ed8eSKurt Hackel 	BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap)));
520c83ed8eSKurt Hackel 
530c83ed8eSKurt Hackel 	if (cluster == NULL)
540c83ed8eSKurt Hackel 		return -EINVAL;
550c83ed8eSKurt Hackel 
560c83ed8eSKurt Hackel 	read_lock(&cluster->cl_nodes_lock);
57*71dd5d65SJoseph Qi 	bitmap_copy(map, cluster->cl_nodes_bitmap, O2NM_MAX_NODES);
580c83ed8eSKurt Hackel 	read_unlock(&cluster->cl_nodes_lock);
590c83ed8eSKurt Hackel 
600c83ed8eSKurt Hackel 	return 0;
610c83ed8eSKurt Hackel }
620c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_configured_node_map);
630c83ed8eSKurt Hackel 
o2nm_node_ip_tree_lookup(struct o2nm_cluster * cluster,__be32 ip_needle,struct rb_node *** ret_p,struct rb_node ** ret_parent)640c83ed8eSKurt Hackel static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster,
650c83ed8eSKurt Hackel 						  __be32 ip_needle,
660c83ed8eSKurt Hackel 						  struct rb_node ***ret_p,
670c83ed8eSKurt Hackel 						  struct rb_node **ret_parent)
680c83ed8eSKurt Hackel {
690c83ed8eSKurt Hackel 	struct rb_node **p = &cluster->cl_node_ip_tree.rb_node;
700c83ed8eSKurt Hackel 	struct rb_node *parent = NULL;
710c83ed8eSKurt Hackel 	struct o2nm_node *node, *ret = NULL;
720c83ed8eSKurt Hackel 
730c83ed8eSKurt Hackel 	while (*p) {
7479cd22d3SAkinobu Mita 		int cmp;
7579cd22d3SAkinobu Mita 
760c83ed8eSKurt Hackel 		parent = *p;
770c83ed8eSKurt Hackel 		node = rb_entry(parent, struct o2nm_node, nd_ip_node);
780c83ed8eSKurt Hackel 
7979cd22d3SAkinobu Mita 		cmp = memcmp(&ip_needle, &node->nd_ipv4_address,
8079cd22d3SAkinobu Mita 				sizeof(ip_needle));
8179cd22d3SAkinobu Mita 		if (cmp < 0)
820c83ed8eSKurt Hackel 			p = &(*p)->rb_left;
8379cd22d3SAkinobu Mita 		else if (cmp > 0)
840c83ed8eSKurt Hackel 			p = &(*p)->rb_right;
850c83ed8eSKurt Hackel 		else {
860c83ed8eSKurt Hackel 			ret = node;
870c83ed8eSKurt Hackel 			break;
880c83ed8eSKurt Hackel 		}
890c83ed8eSKurt Hackel 	}
900c83ed8eSKurt Hackel 
910c83ed8eSKurt Hackel 	if (ret_p != NULL)
920c83ed8eSKurt Hackel 		*ret_p = p;
930c83ed8eSKurt Hackel 	if (ret_parent != NULL)
940c83ed8eSKurt Hackel 		*ret_parent = parent;
950c83ed8eSKurt Hackel 
960c83ed8eSKurt Hackel 	return ret;
970c83ed8eSKurt Hackel }
980c83ed8eSKurt Hackel 
o2nm_get_node_by_ip(__be32 addr)990c83ed8eSKurt Hackel struct o2nm_node *o2nm_get_node_by_ip(__be32 addr)
1000c83ed8eSKurt Hackel {
1010c83ed8eSKurt Hackel 	struct o2nm_node *node = NULL;
1020c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = o2nm_single_cluster;
1030c83ed8eSKurt Hackel 
1040c83ed8eSKurt Hackel 	if (cluster == NULL)
1050c83ed8eSKurt Hackel 		goto out;
1060c83ed8eSKurt Hackel 
1070c83ed8eSKurt Hackel 	read_lock(&cluster->cl_nodes_lock);
1080c83ed8eSKurt Hackel 	node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL);
1090c83ed8eSKurt Hackel 	if (node)
1100c83ed8eSKurt Hackel 		config_item_get(&node->nd_item);
1110c83ed8eSKurt Hackel 	read_unlock(&cluster->cl_nodes_lock);
1120c83ed8eSKurt Hackel 
1130c83ed8eSKurt Hackel out:
1140c83ed8eSKurt Hackel 	return node;
1150c83ed8eSKurt Hackel }
1160c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip);
1170c83ed8eSKurt Hackel 
o2nm_node_put(struct o2nm_node * node)1180c83ed8eSKurt Hackel void o2nm_node_put(struct o2nm_node *node)
1190c83ed8eSKurt Hackel {
1200c83ed8eSKurt Hackel 	config_item_put(&node->nd_item);
1210c83ed8eSKurt Hackel }
1220c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_node_put);
1230c83ed8eSKurt Hackel 
o2nm_node_get(struct o2nm_node * node)1240c83ed8eSKurt Hackel void o2nm_node_get(struct o2nm_node *node)
1250c83ed8eSKurt Hackel {
1260c83ed8eSKurt Hackel 	config_item_get(&node->nd_item);
1270c83ed8eSKurt Hackel }
1280c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_node_get);
1290c83ed8eSKurt Hackel 
o2nm_this_node(void)1300c83ed8eSKurt Hackel u8 o2nm_this_node(void)
1310c83ed8eSKurt Hackel {
1320c83ed8eSKurt Hackel 	u8 node_num = O2NM_MAX_NODES;
1330c83ed8eSKurt Hackel 
1340c83ed8eSKurt Hackel 	if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local)
1350c83ed8eSKurt Hackel 		node_num = o2nm_single_cluster->cl_local_node;
1360c83ed8eSKurt Hackel 
1370c83ed8eSKurt Hackel 	return node_num;
1380c83ed8eSKurt Hackel }
1390c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_this_node);
1400c83ed8eSKurt Hackel 
1410c83ed8eSKurt Hackel /* node configfs bits */
1420c83ed8eSKurt Hackel 
to_o2nm_cluster(struct config_item * item)1430c83ed8eSKurt Hackel static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item)
1440c83ed8eSKurt Hackel {
1450c83ed8eSKurt Hackel 	return item ?
1460c83ed8eSKurt Hackel 		container_of(to_config_group(item), struct o2nm_cluster,
1470c83ed8eSKurt Hackel 			     cl_group)
1480c83ed8eSKurt Hackel 		: NULL;
1490c83ed8eSKurt Hackel }
1500c83ed8eSKurt Hackel 
to_o2nm_node(struct config_item * item)1510c83ed8eSKurt Hackel static struct o2nm_node *to_o2nm_node(struct config_item *item)
1520c83ed8eSKurt Hackel {
1530c83ed8eSKurt Hackel 	return item ? container_of(item, struct o2nm_node, nd_item) : NULL;
1540c83ed8eSKurt Hackel }
1550c83ed8eSKurt Hackel 
o2nm_node_release(struct config_item * item)1560c83ed8eSKurt Hackel static void o2nm_node_release(struct config_item *item)
1570c83ed8eSKurt Hackel {
1580c83ed8eSKurt Hackel 	struct o2nm_node *node = to_o2nm_node(item);
1590c83ed8eSKurt Hackel 	kfree(node);
1600c83ed8eSKurt Hackel }
1610c83ed8eSKurt Hackel 
o2nm_node_num_show(struct config_item * item,char * page)16245b99773SChristoph Hellwig static ssize_t o2nm_node_num_show(struct config_item *item, char *page)
1630c83ed8eSKurt Hackel {
16445b99773SChristoph Hellwig 	return sprintf(page, "%d\n", to_o2nm_node(item)->nd_num);
1650c83ed8eSKurt Hackel }
1660c83ed8eSKurt Hackel 
to_o2nm_cluster_from_node(struct o2nm_node * node)1670c83ed8eSKurt Hackel static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node)
1680c83ed8eSKurt Hackel {
1690c83ed8eSKurt Hackel 	/* through the first node_set .parent
1700c83ed8eSKurt Hackel 	 * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */
171853bc26aSalex chen 	if (node->nd_item.ci_parent)
1720c83ed8eSKurt Hackel 		return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent);
173853bc26aSalex chen 	else
174853bc26aSalex chen 		return NULL;
1750c83ed8eSKurt Hackel }
1760c83ed8eSKurt Hackel 
1770c83ed8eSKurt Hackel enum {
1780c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_NUM = 0,
1790c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_PORT,
1800c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_ADDRESS,
1810c83ed8eSKurt Hackel };
1820c83ed8eSKurt Hackel 
o2nm_node_num_store(struct config_item * item,const char * page,size_t count)18345b99773SChristoph Hellwig static ssize_t o2nm_node_num_store(struct config_item *item, const char *page,
1840c83ed8eSKurt Hackel 				   size_t count)
1850c83ed8eSKurt Hackel {
18645b99773SChristoph Hellwig 	struct o2nm_node *node = to_o2nm_node(item);
187853bc26aSalex chen 	struct o2nm_cluster *cluster;
1880c83ed8eSKurt Hackel 	unsigned long tmp;
1890c83ed8eSKurt Hackel 	char *p = (char *)page;
19013a83fc9SChristoph Hellwig 	int ret = 0;
1910c83ed8eSKurt Hackel 
1920c83ed8eSKurt Hackel 	tmp = simple_strtoul(p, &p, 0);
1930c83ed8eSKurt Hackel 	if (!p || (*p && (*p != '\n')))
1940c83ed8eSKurt Hackel 		return -EINVAL;
1950c83ed8eSKurt Hackel 
1960c83ed8eSKurt Hackel 	if (tmp >= O2NM_MAX_NODES)
1970c83ed8eSKurt Hackel 		return -ERANGE;
1980c83ed8eSKurt Hackel 
1990c83ed8eSKurt Hackel 	/* once we're in the cl_nodes tree networking can look us up by
2000c83ed8eSKurt Hackel 	 * node number and try to use our address and port attributes
2010c83ed8eSKurt Hackel 	 * to connect to this node.. make sure that they've been set
2020c83ed8eSKurt Hackel 	 * before writing the node attribute? */
2030c83ed8eSKurt Hackel 	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
2040c83ed8eSKurt Hackel 	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
2050c83ed8eSKurt Hackel 		return -EINVAL; /* XXX */
2060c83ed8eSKurt Hackel 
207853bc26aSalex chen 	o2nm_lock_subsystem();
208853bc26aSalex chen 	cluster = to_o2nm_cluster_from_node(node);
209853bc26aSalex chen 	if (!cluster) {
210853bc26aSalex chen 		o2nm_unlock_subsystem();
211853bc26aSalex chen 		return -EINVAL;
212853bc26aSalex chen 	}
213853bc26aSalex chen 
2140c83ed8eSKurt Hackel 	write_lock(&cluster->cl_nodes_lock);
2150c83ed8eSKurt Hackel 	if (cluster->cl_nodes[tmp])
21613a83fc9SChristoph Hellwig 		ret = -EEXIST;
21713a83fc9SChristoph Hellwig 	else if (test_and_set_bit(O2NM_NODE_ATTR_NUM,
21813a83fc9SChristoph Hellwig 			&node->nd_set_attributes))
21913a83fc9SChristoph Hellwig 		ret = -EBUSY;
2200c83ed8eSKurt Hackel 	else  {
2210c83ed8eSKurt Hackel 		cluster->cl_nodes[tmp] = node;
2220c83ed8eSKurt Hackel 		node->nd_num = tmp;
2230c83ed8eSKurt Hackel 		set_bit(tmp, cluster->cl_nodes_bitmap);
2240c83ed8eSKurt Hackel 	}
2250c83ed8eSKurt Hackel 	write_unlock(&cluster->cl_nodes_lock);
226853bc26aSalex chen 	o2nm_unlock_subsystem();
227853bc26aSalex chen 
22813a83fc9SChristoph Hellwig 	if (ret)
22913a83fc9SChristoph Hellwig 		return ret;
2300c83ed8eSKurt Hackel 
2310c83ed8eSKurt Hackel 	return count;
2320c83ed8eSKurt Hackel }
o2nm_node_ipv4_port_show(struct config_item * item,char * page)23345b99773SChristoph Hellwig static ssize_t o2nm_node_ipv4_port_show(struct config_item *item, char *page)
2340c83ed8eSKurt Hackel {
23545b99773SChristoph Hellwig 	return sprintf(page, "%u\n", ntohs(to_o2nm_node(item)->nd_ipv4_port));
2360c83ed8eSKurt Hackel }
2370c83ed8eSKurt Hackel 
o2nm_node_ipv4_port_store(struct config_item * item,const char * page,size_t count)23845b99773SChristoph Hellwig static ssize_t o2nm_node_ipv4_port_store(struct config_item *item,
2390c83ed8eSKurt Hackel 					 const char *page, size_t count)
2400c83ed8eSKurt Hackel {
24145b99773SChristoph Hellwig 	struct o2nm_node *node = to_o2nm_node(item);
2420c83ed8eSKurt Hackel 	unsigned long tmp;
2430c83ed8eSKurt Hackel 	char *p = (char *)page;
2440c83ed8eSKurt Hackel 
2450c83ed8eSKurt Hackel 	tmp = simple_strtoul(p, &p, 0);
2460c83ed8eSKurt Hackel 	if (!p || (*p && (*p != '\n')))
2470c83ed8eSKurt Hackel 		return -EINVAL;
2480c83ed8eSKurt Hackel 
2490c83ed8eSKurt Hackel 	if (tmp == 0)
2500c83ed8eSKurt Hackel 		return -EINVAL;
2510c83ed8eSKurt Hackel 	if (tmp >= (u16)-1)
2520c83ed8eSKurt Hackel 		return -ERANGE;
2530c83ed8eSKurt Hackel 
25413a83fc9SChristoph Hellwig 	if (test_and_set_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
25513a83fc9SChristoph Hellwig 		return -EBUSY;
2560c83ed8eSKurt Hackel 	node->nd_ipv4_port = htons(tmp);
2570c83ed8eSKurt Hackel 
2580c83ed8eSKurt Hackel 	return count;
2590c83ed8eSKurt Hackel }
2600c83ed8eSKurt Hackel 
o2nm_node_ipv4_address_show(struct config_item * item,char * page)26145b99773SChristoph Hellwig static ssize_t o2nm_node_ipv4_address_show(struct config_item *item, char *page)
2620c83ed8eSKurt Hackel {
26345b99773SChristoph Hellwig 	return sprintf(page, "%pI4\n", &to_o2nm_node(item)->nd_ipv4_address);
2640c83ed8eSKurt Hackel }
2650c83ed8eSKurt Hackel 
o2nm_node_ipv4_address_store(struct config_item * item,const char * page,size_t count)26645b99773SChristoph Hellwig static ssize_t o2nm_node_ipv4_address_store(struct config_item *item,
2670c83ed8eSKurt Hackel 					    const char *page,
2680c83ed8eSKurt Hackel 					    size_t count)
2690c83ed8eSKurt Hackel {
27045b99773SChristoph Hellwig 	struct o2nm_node *node = to_o2nm_node(item);
271853bc26aSalex chen 	struct o2nm_cluster *cluster;
2720c83ed8eSKurt Hackel 	int ret, i;
2730c83ed8eSKurt Hackel 	struct rb_node **p, *parent;
2740c83ed8eSKurt Hackel 	unsigned int octets[4];
2750c83ed8eSKurt Hackel 	__be32 ipv4_addr = 0;
2760c83ed8eSKurt Hackel 
2770c83ed8eSKurt Hackel 	ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2],
2780c83ed8eSKurt Hackel 		     &octets[1], &octets[0]);
2790c83ed8eSKurt Hackel 	if (ret != 4)
2800c83ed8eSKurt Hackel 		return -EINVAL;
2810c83ed8eSKurt Hackel 
2820c83ed8eSKurt Hackel 	for (i = 0; i < ARRAY_SIZE(octets); i++) {
2830c83ed8eSKurt Hackel 		if (octets[i] > 255)
2840c83ed8eSKurt Hackel 			return -ERANGE;
2850c83ed8eSKurt Hackel 		be32_add_cpu(&ipv4_addr, octets[i] << (i * 8));
2860c83ed8eSKurt Hackel 	}
2870c83ed8eSKurt Hackel 
288853bc26aSalex chen 	o2nm_lock_subsystem();
289853bc26aSalex chen 	cluster = to_o2nm_cluster_from_node(node);
290853bc26aSalex chen 	if (!cluster) {
291853bc26aSalex chen 		o2nm_unlock_subsystem();
292853bc26aSalex chen 		return -EINVAL;
293853bc26aSalex chen 	}
294853bc26aSalex chen 
2950c83ed8eSKurt Hackel 	ret = 0;
2960c83ed8eSKurt Hackel 	write_lock(&cluster->cl_nodes_lock);
2970c83ed8eSKurt Hackel 	if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
2980c83ed8eSKurt Hackel 		ret = -EEXIST;
29913a83fc9SChristoph Hellwig 	else if (test_and_set_bit(O2NM_NODE_ATTR_ADDRESS,
30013a83fc9SChristoph Hellwig 			&node->nd_set_attributes))
30113a83fc9SChristoph Hellwig 		ret = -EBUSY;
3020c83ed8eSKurt Hackel 	else {
3030c83ed8eSKurt Hackel 		rb_link_node(&node->nd_ip_node, parent, p);
3040c83ed8eSKurt Hackel 		rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
3050c83ed8eSKurt Hackel 	}
3060c83ed8eSKurt Hackel 	write_unlock(&cluster->cl_nodes_lock);
307853bc26aSalex chen 	o2nm_unlock_subsystem();
308853bc26aSalex chen 
3090c83ed8eSKurt Hackel 	if (ret)
3100c83ed8eSKurt Hackel 		return ret;
3110c83ed8eSKurt Hackel 
3120c83ed8eSKurt Hackel 	memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr));
3130c83ed8eSKurt Hackel 
3140c83ed8eSKurt Hackel 	return count;
3150c83ed8eSKurt Hackel }
3160c83ed8eSKurt Hackel 
o2nm_node_local_show(struct config_item * item,char * page)31745b99773SChristoph Hellwig static ssize_t o2nm_node_local_show(struct config_item *item, char *page)
3180c83ed8eSKurt Hackel {
31945b99773SChristoph Hellwig 	return sprintf(page, "%d\n", to_o2nm_node(item)->nd_local);
3200c83ed8eSKurt Hackel }
3210c83ed8eSKurt Hackel 
o2nm_node_local_store(struct config_item * item,const char * page,size_t count)32245b99773SChristoph Hellwig static ssize_t o2nm_node_local_store(struct config_item *item, const char *page,
3230c83ed8eSKurt Hackel 				     size_t count)
3240c83ed8eSKurt Hackel {
32545b99773SChristoph Hellwig 	struct o2nm_node *node = to_o2nm_node(item);
326853bc26aSalex chen 	struct o2nm_cluster *cluster;
3270c83ed8eSKurt Hackel 	unsigned long tmp;
3280c83ed8eSKurt Hackel 	char *p = (char *)page;
3290c83ed8eSKurt Hackel 	ssize_t ret;
3300c83ed8eSKurt Hackel 
3310c83ed8eSKurt Hackel 	tmp = simple_strtoul(p, &p, 0);
3320c83ed8eSKurt Hackel 	if (!p || (*p && (*p != '\n')))
3330c83ed8eSKurt Hackel 		return -EINVAL;
3340c83ed8eSKurt Hackel 
3350c83ed8eSKurt Hackel 	tmp = !!tmp; /* boolean of whether this node wants to be local */
3360c83ed8eSKurt Hackel 
3370c83ed8eSKurt Hackel 	/* setting local turns on networking rx for now so we require having
3380c83ed8eSKurt Hackel 	 * set everything else first */
3390c83ed8eSKurt Hackel 	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
3400c83ed8eSKurt Hackel 	    !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) ||
3410c83ed8eSKurt Hackel 	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
3420c83ed8eSKurt Hackel 		return -EINVAL; /* XXX */
3430c83ed8eSKurt Hackel 
344853bc26aSalex chen 	o2nm_lock_subsystem();
345853bc26aSalex chen 	cluster = to_o2nm_cluster_from_node(node);
346853bc26aSalex chen 	if (!cluster) {
347853bc26aSalex chen 		ret = -EINVAL;
348853bc26aSalex chen 		goto out;
349853bc26aSalex chen 	}
350853bc26aSalex chen 
3510c83ed8eSKurt Hackel 	/* the only failure case is trying to set a new local node
3520c83ed8eSKurt Hackel 	 * when a different one is already set */
3530c83ed8eSKurt Hackel 	if (tmp && tmp == cluster->cl_has_local &&
354853bc26aSalex chen 	    cluster->cl_local_node != node->nd_num) {
355853bc26aSalex chen 		ret = -EBUSY;
356853bc26aSalex chen 		goto out;
357853bc26aSalex chen 	}
3580c83ed8eSKurt Hackel 
3590c83ed8eSKurt Hackel 	/* bring up the rx thread if we're setting the new local node. */
3600c83ed8eSKurt Hackel 	if (tmp && !cluster->cl_has_local) {
3610c83ed8eSKurt Hackel 		ret = o2net_start_listening(node);
3620c83ed8eSKurt Hackel 		if (ret)
363853bc26aSalex chen 			goto out;
3640c83ed8eSKurt Hackel 	}
3650c83ed8eSKurt Hackel 
3660c83ed8eSKurt Hackel 	if (!tmp && cluster->cl_has_local &&
3670c83ed8eSKurt Hackel 	    cluster->cl_local_node == node->nd_num) {
3680c83ed8eSKurt Hackel 		o2net_stop_listening(node);
3690c83ed8eSKurt Hackel 		cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
3700c83ed8eSKurt Hackel 	}
3710c83ed8eSKurt Hackel 
3720c83ed8eSKurt Hackel 	node->nd_local = tmp;
3730c83ed8eSKurt Hackel 	if (node->nd_local) {
3740c83ed8eSKurt Hackel 		cluster->cl_has_local = tmp;
3750c83ed8eSKurt Hackel 		cluster->cl_local_node = node->nd_num;
3760c83ed8eSKurt Hackel 	}
3770c83ed8eSKurt Hackel 
378853bc26aSalex chen 	ret = count;
379853bc26aSalex chen 
380853bc26aSalex chen out:
381853bc26aSalex chen 	o2nm_unlock_subsystem();
382853bc26aSalex chen 	return ret;
3830c83ed8eSKurt Hackel }
3840c83ed8eSKurt Hackel 
38545b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_node_, num);
38645b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_node_, ipv4_port);
38745b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_node_, ipv4_address);
38845b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_node_, local);
3890c83ed8eSKurt Hackel 
3900c83ed8eSKurt Hackel static struct configfs_attribute *o2nm_node_attrs[] = {
39145b99773SChristoph Hellwig 	&o2nm_node_attr_num,
39245b99773SChristoph Hellwig 	&o2nm_node_attr_ipv4_port,
39345b99773SChristoph Hellwig 	&o2nm_node_attr_ipv4_address,
39445b99773SChristoph Hellwig 	&o2nm_node_attr_local,
3950c83ed8eSKurt Hackel 	NULL,
3960c83ed8eSKurt Hackel };
3970c83ed8eSKurt Hackel 
3980c83ed8eSKurt Hackel static struct configfs_item_operations o2nm_node_item_ops = {
3990c83ed8eSKurt Hackel 	.release		= o2nm_node_release,
4000c83ed8eSKurt Hackel };
4010c83ed8eSKurt Hackel 
4024843afe4SBhumika Goyal static const struct config_item_type o2nm_node_type = {
4030c83ed8eSKurt Hackel 	.ct_item_ops	= &o2nm_node_item_ops,
4040c83ed8eSKurt Hackel 	.ct_attrs	= o2nm_node_attrs,
4050c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
4060c83ed8eSKurt Hackel };
4070c83ed8eSKurt Hackel 
4080c83ed8eSKurt Hackel /* node set */
4090c83ed8eSKurt Hackel 
4100c83ed8eSKurt Hackel struct o2nm_node_group {
4110c83ed8eSKurt Hackel 	struct config_group ns_group;
4120c83ed8eSKurt Hackel 	/* some stuff? */
4130c83ed8eSKurt Hackel };
4140c83ed8eSKurt Hackel 
4150c83ed8eSKurt Hackel #if 0
4160c83ed8eSKurt Hackel static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
4170c83ed8eSKurt Hackel {
4180c83ed8eSKurt Hackel 	return group ?
4190c83ed8eSKurt Hackel 		container_of(group, struct o2nm_node_group, ns_group)
4200c83ed8eSKurt Hackel 		: NULL;
4210c83ed8eSKurt Hackel }
4220c83ed8eSKurt Hackel #endif
4230c83ed8eSKurt Hackel 
o2nm_cluster_attr_write(const char * page,ssize_t count,unsigned int * val)424b5dd8030SJeff Mahoney static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
425b5dd8030SJeff Mahoney                                        unsigned int *val)
426b5dd8030SJeff Mahoney {
427b5dd8030SJeff Mahoney 	unsigned long tmp;
428b5dd8030SJeff Mahoney 	char *p = (char *)page;
429b5dd8030SJeff Mahoney 
430b5dd8030SJeff Mahoney 	tmp = simple_strtoul(p, &p, 0);
431b5dd8030SJeff Mahoney 	if (!p || (*p && (*p != '\n')))
432b5dd8030SJeff Mahoney 		return -EINVAL;
433b5dd8030SJeff Mahoney 
434b5dd8030SJeff Mahoney 	if (tmp == 0)
435b5dd8030SJeff Mahoney 		return -EINVAL;
436b5dd8030SJeff Mahoney 	if (tmp >= (u32)-1)
437b5dd8030SJeff Mahoney 		return -ERANGE;
438b5dd8030SJeff Mahoney 
439b5dd8030SJeff Mahoney 	*val = tmp;
440b5dd8030SJeff Mahoney 
441b5dd8030SJeff Mahoney 	return count;
442b5dd8030SJeff Mahoney }
443b5dd8030SJeff Mahoney 
o2nm_cluster_idle_timeout_ms_show(struct config_item * item,char * page)44445b99773SChristoph Hellwig static ssize_t o2nm_cluster_idle_timeout_ms_show(struct config_item *item,
44545b99773SChristoph Hellwig 	char *page)
446b5dd8030SJeff Mahoney {
44745b99773SChristoph Hellwig 	return sprintf(page, "%u\n", to_o2nm_cluster(item)->cl_idle_timeout_ms);
448b5dd8030SJeff Mahoney }
449b5dd8030SJeff Mahoney 
o2nm_cluster_idle_timeout_ms_store(struct config_item * item,const char * page,size_t count)45045b99773SChristoph Hellwig static ssize_t o2nm_cluster_idle_timeout_ms_store(struct config_item *item,
45145b99773SChristoph Hellwig 	const char *page, size_t count)
452b5dd8030SJeff Mahoney {
45345b99773SChristoph Hellwig 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
454b5dd8030SJeff Mahoney 	ssize_t ret;
455b5dd8030SJeff Mahoney 	unsigned int val;
456b5dd8030SJeff Mahoney 
457b5dd8030SJeff Mahoney 	ret =  o2nm_cluster_attr_write(page, count, &val);
458b5dd8030SJeff Mahoney 
459b5dd8030SJeff Mahoney 	if (ret > 0) {
460828ae6afSAndrew Beekhof 		if (cluster->cl_idle_timeout_ms != val
461828ae6afSAndrew Beekhof 			&& o2net_num_connected_peers()) {
462828ae6afSAndrew Beekhof 			mlog(ML_NOTICE,
463828ae6afSAndrew Beekhof 			     "o2net: cannot change idle timeout after "
464828ae6afSAndrew Beekhof 			     "the first peer has agreed to it."
465828ae6afSAndrew Beekhof 			     "  %d connected peers\n",
466828ae6afSAndrew Beekhof 			     o2net_num_connected_peers());
467828ae6afSAndrew Beekhof 			ret = -EINVAL;
468828ae6afSAndrew Beekhof 		} else if (val <= cluster->cl_keepalive_delay_ms) {
469b5dd8030SJeff Mahoney 			mlog(ML_NOTICE, "o2net: idle timeout must be larger "
470b5dd8030SJeff Mahoney 			     "than keepalive delay\n");
471828ae6afSAndrew Beekhof 			ret = -EINVAL;
472828ae6afSAndrew Beekhof 		} else {
473b5dd8030SJeff Mahoney 			cluster->cl_idle_timeout_ms = val;
474b5dd8030SJeff Mahoney 		}
475828ae6afSAndrew Beekhof 	}
476b5dd8030SJeff Mahoney 
477b5dd8030SJeff Mahoney 	return ret;
478b5dd8030SJeff Mahoney }
479b5dd8030SJeff Mahoney 
o2nm_cluster_keepalive_delay_ms_show(struct config_item * item,char * page)48045b99773SChristoph Hellwig static ssize_t o2nm_cluster_keepalive_delay_ms_show(
48145b99773SChristoph Hellwig 	struct config_item *item, char *page)
482b5dd8030SJeff Mahoney {
48345b99773SChristoph Hellwig 	return sprintf(page, "%u\n",
48445b99773SChristoph Hellwig 			to_o2nm_cluster(item)->cl_keepalive_delay_ms);
485b5dd8030SJeff Mahoney }
486b5dd8030SJeff Mahoney 
o2nm_cluster_keepalive_delay_ms_store(struct config_item * item,const char * page,size_t count)48745b99773SChristoph Hellwig static ssize_t o2nm_cluster_keepalive_delay_ms_store(
48845b99773SChristoph Hellwig 	struct config_item *item, const char *page, size_t count)
489b5dd8030SJeff Mahoney {
49045b99773SChristoph Hellwig 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
491b5dd8030SJeff Mahoney 	ssize_t ret;
492b5dd8030SJeff Mahoney 	unsigned int val;
493b5dd8030SJeff Mahoney 
494b5dd8030SJeff Mahoney 	ret =  o2nm_cluster_attr_write(page, count, &val);
495b5dd8030SJeff Mahoney 
496b5dd8030SJeff Mahoney 	if (ret > 0) {
497828ae6afSAndrew Beekhof 		if (cluster->cl_keepalive_delay_ms != val
498828ae6afSAndrew Beekhof 		    && o2net_num_connected_peers()) {
499828ae6afSAndrew Beekhof 			mlog(ML_NOTICE,
500828ae6afSAndrew Beekhof 			     "o2net: cannot change keepalive delay after"
501828ae6afSAndrew Beekhof 			     " the first peer has agreed to it."
502828ae6afSAndrew Beekhof 			     "  %d connected peers\n",
503828ae6afSAndrew Beekhof 			     o2net_num_connected_peers());
504828ae6afSAndrew Beekhof 			ret = -EINVAL;
505828ae6afSAndrew Beekhof 		} else if (val >= cluster->cl_idle_timeout_ms) {
506b5dd8030SJeff Mahoney 			mlog(ML_NOTICE, "o2net: keepalive delay must be "
507b5dd8030SJeff Mahoney 			     "smaller than idle timeout\n");
508828ae6afSAndrew Beekhof 			ret = -EINVAL;
509828ae6afSAndrew Beekhof 		} else {
510b5dd8030SJeff Mahoney 			cluster->cl_keepalive_delay_ms = val;
511b5dd8030SJeff Mahoney 		}
512828ae6afSAndrew Beekhof 	}
513b5dd8030SJeff Mahoney 
514b5dd8030SJeff Mahoney 	return ret;
515b5dd8030SJeff Mahoney }
516b5dd8030SJeff Mahoney 
o2nm_cluster_reconnect_delay_ms_show(struct config_item * item,char * page)51745b99773SChristoph Hellwig static ssize_t o2nm_cluster_reconnect_delay_ms_show(
51845b99773SChristoph Hellwig 	struct config_item *item, char *page)
519b5dd8030SJeff Mahoney {
52045b99773SChristoph Hellwig 	return sprintf(page, "%u\n",
52145b99773SChristoph Hellwig 			to_o2nm_cluster(item)->cl_reconnect_delay_ms);
522b5dd8030SJeff Mahoney }
523b5dd8030SJeff Mahoney 
o2nm_cluster_reconnect_delay_ms_store(struct config_item * item,const char * page,size_t count)52445b99773SChristoph Hellwig static ssize_t o2nm_cluster_reconnect_delay_ms_store(
52545b99773SChristoph Hellwig 	struct config_item *item, const char *page, size_t count)
526b5dd8030SJeff Mahoney {
527b5dd8030SJeff Mahoney 	return o2nm_cluster_attr_write(page, count,
52845b99773SChristoph Hellwig                                &to_o2nm_cluster(item)->cl_reconnect_delay_ms);
529b5dd8030SJeff Mahoney }
530f6656d26SSunil Mushran 
o2nm_cluster_fence_method_show(struct config_item * item,char * page)53145b99773SChristoph Hellwig static ssize_t o2nm_cluster_fence_method_show(
53245b99773SChristoph Hellwig 	struct config_item *item, char *page)
533f6656d26SSunil Mushran {
53445b99773SChristoph Hellwig 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
535f6656d26SSunil Mushran 	ssize_t ret = 0;
536f6656d26SSunil Mushran 
537f6656d26SSunil Mushran 	if (cluster)
538f6656d26SSunil Mushran 		ret = sprintf(page, "%s\n",
539f6656d26SSunil Mushran 			      o2nm_fence_method_desc[cluster->cl_fence_method]);
540f6656d26SSunil Mushran 	return ret;
541f6656d26SSunil Mushran }
542f6656d26SSunil Mushran 
o2nm_cluster_fence_method_store(struct config_item * item,const char * page,size_t count)54345b99773SChristoph Hellwig static ssize_t o2nm_cluster_fence_method_store(
54445b99773SChristoph Hellwig 	struct config_item *item, const char *page, size_t count)
545f6656d26SSunil Mushran {
546f6656d26SSunil Mushran 	unsigned int i;
547f6656d26SSunil Mushran 
548f6656d26SSunil Mushran 	if (page[count - 1] != '\n')
549f6656d26SSunil Mushran 		goto bail;
550f6656d26SSunil Mushran 
551f6656d26SSunil Mushran 	for (i = 0; i < O2NM_FENCE_METHODS; ++i) {
552f6656d26SSunil Mushran 		if (count != strlen(o2nm_fence_method_desc[i]) + 1)
553f6656d26SSunil Mushran 			continue;
554f6656d26SSunil Mushran 		if (strncasecmp(page, o2nm_fence_method_desc[i], count - 1))
555f6656d26SSunil Mushran 			continue;
55645b99773SChristoph Hellwig 		if (to_o2nm_cluster(item)->cl_fence_method != i) {
557f6656d26SSunil Mushran 			printk(KERN_INFO "ocfs2: Changing fence method to %s\n",
558f6656d26SSunil Mushran 			       o2nm_fence_method_desc[i]);
55945b99773SChristoph Hellwig 			to_o2nm_cluster(item)->cl_fence_method = i;
560f6656d26SSunil Mushran 		}
561f6656d26SSunil Mushran 		return count;
562f6656d26SSunil Mushran 	}
563f6656d26SSunil Mushran 
564f6656d26SSunil Mushran bail:
565f6656d26SSunil Mushran 	return -EINVAL;
566f6656d26SSunil Mushran }
567f6656d26SSunil Mushran 
56845b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_cluster_, idle_timeout_ms);
56945b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_cluster_, keepalive_delay_ms);
57045b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_cluster_, reconnect_delay_ms);
57145b99773SChristoph Hellwig CONFIGFS_ATTR(o2nm_cluster_, fence_method);
572f6656d26SSunil Mushran 
573b5dd8030SJeff Mahoney static struct configfs_attribute *o2nm_cluster_attrs[] = {
57445b99773SChristoph Hellwig 	&o2nm_cluster_attr_idle_timeout_ms,
57545b99773SChristoph Hellwig 	&o2nm_cluster_attr_keepalive_delay_ms,
57645b99773SChristoph Hellwig 	&o2nm_cluster_attr_reconnect_delay_ms,
57745b99773SChristoph Hellwig 	&o2nm_cluster_attr_fence_method,
578b5dd8030SJeff Mahoney 	NULL,
579b5dd8030SJeff Mahoney };
580b5dd8030SJeff Mahoney 
o2nm_node_group_make_item(struct config_group * group,const char * name)581f89ab861SJoel Becker static struct config_item *o2nm_node_group_make_item(struct config_group *group,
582f89ab861SJoel Becker 						     const char *name)
5830c83ed8eSKurt Hackel {
5840c83ed8eSKurt Hackel 	struct o2nm_node *node = NULL;
5850c83ed8eSKurt Hackel 
586f89ab861SJoel Becker 	if (strlen(name) > O2NM_MAX_NAME_LEN)
587a6795e9eSJoel Becker 		return ERR_PTR(-ENAMETOOLONG);
5880c83ed8eSKurt Hackel 
589cd861280SRobert P. J. Day 	node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
590f89ab861SJoel Becker 	if (node == NULL)
591a6795e9eSJoel Becker 		return ERR_PTR(-ENOMEM);
5920c83ed8eSKurt Hackel 
5930c83ed8eSKurt Hackel 	strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
5940c83ed8eSKurt Hackel 	config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
5950c83ed8eSKurt Hackel 	spin_lock_init(&node->nd_lock);
5960c83ed8eSKurt Hackel 
59739a29856SSunil Mushran 	mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name);
59839a29856SSunil Mushran 
599a6795e9eSJoel Becker 	return &node->nd_item;
6000c83ed8eSKurt Hackel }
6010c83ed8eSKurt Hackel 
o2nm_node_group_drop_item(struct config_group * group,struct config_item * item)6020c83ed8eSKurt Hackel static void o2nm_node_group_drop_item(struct config_group *group,
6030c83ed8eSKurt Hackel 				      struct config_item *item)
6040c83ed8eSKurt Hackel {
6050c83ed8eSKurt Hackel 	struct o2nm_node *node = to_o2nm_node(item);
6060c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent);
6070c83ed8eSKurt Hackel 
608cc725ef3SJia Guo 	if (cluster->cl_nodes[node->nd_num] == node) {
6090c83ed8eSKurt Hackel 		o2net_disconnect_node(node);
6100c83ed8eSKurt Hackel 
6110c83ed8eSKurt Hackel 		if (cluster->cl_has_local &&
6120c83ed8eSKurt Hackel 		    (cluster->cl_local_node == node->nd_num)) {
6130c83ed8eSKurt Hackel 			cluster->cl_has_local = 0;
6140c83ed8eSKurt Hackel 			cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
6150c83ed8eSKurt Hackel 			o2net_stop_listening(node);
6160c83ed8eSKurt Hackel 		}
617cc725ef3SJia Guo 	}
6180c83ed8eSKurt Hackel 
6190c83ed8eSKurt Hackel 	/* XXX call into net to stop this node from trading messages */
6200c83ed8eSKurt Hackel 
6210c83ed8eSKurt Hackel 	write_lock(&cluster->cl_nodes_lock);
6220c83ed8eSKurt Hackel 
6230c83ed8eSKurt Hackel 	/* XXX sloppy */
6240c83ed8eSKurt Hackel 	if (node->nd_ipv4_address)
6250c83ed8eSKurt Hackel 		rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree);
6260c83ed8eSKurt Hackel 
6270c83ed8eSKurt Hackel 	/* nd_num might be 0 if the node number hasn't been set.. */
6280c83ed8eSKurt Hackel 	if (cluster->cl_nodes[node->nd_num] == node) {
6290c83ed8eSKurt Hackel 		cluster->cl_nodes[node->nd_num] = NULL;
6300c83ed8eSKurt Hackel 		clear_bit(node->nd_num, cluster->cl_nodes_bitmap);
6310c83ed8eSKurt Hackel 	}
6320c83ed8eSKurt Hackel 	write_unlock(&cluster->cl_nodes_lock);
6330c83ed8eSKurt Hackel 
63439a29856SSunil Mushran 	mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n",
63539a29856SSunil Mushran 	     config_item_name(&node->nd_item));
63639a29856SSunil Mushran 
6370c83ed8eSKurt Hackel 	config_item_put(item);
6380c83ed8eSKurt Hackel }
6390c83ed8eSKurt Hackel 
6400c83ed8eSKurt Hackel static struct configfs_group_operations o2nm_node_group_group_ops = {
6410c83ed8eSKurt Hackel 	.make_item	= o2nm_node_group_make_item,
6420c83ed8eSKurt Hackel 	.drop_item	= o2nm_node_group_drop_item,
6430c83ed8eSKurt Hackel };
6440c83ed8eSKurt Hackel 
6454843afe4SBhumika Goyal static const struct config_item_type o2nm_node_group_type = {
6460c83ed8eSKurt Hackel 	.ct_group_ops	= &o2nm_node_group_group_ops,
6470c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
6480c83ed8eSKurt Hackel };
6490c83ed8eSKurt Hackel 
6500c83ed8eSKurt Hackel /* cluster */
6510c83ed8eSKurt Hackel 
o2nm_cluster_release(struct config_item * item)6520c83ed8eSKurt Hackel static void o2nm_cluster_release(struct config_item *item)
6530c83ed8eSKurt Hackel {
6540c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
6550c83ed8eSKurt Hackel 
6560c83ed8eSKurt Hackel 	kfree(cluster);
6570c83ed8eSKurt Hackel }
6580c83ed8eSKurt Hackel 
6590c83ed8eSKurt Hackel static struct configfs_item_operations o2nm_cluster_item_ops = {
6600c83ed8eSKurt Hackel 	.release	= o2nm_cluster_release,
6610c83ed8eSKurt Hackel };
6620c83ed8eSKurt Hackel 
6634843afe4SBhumika Goyal static const struct config_item_type o2nm_cluster_type = {
6640c83ed8eSKurt Hackel 	.ct_item_ops	= &o2nm_cluster_item_ops,
665b5dd8030SJeff Mahoney 	.ct_attrs	= o2nm_cluster_attrs,
6660c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
6670c83ed8eSKurt Hackel };
6680c83ed8eSKurt Hackel 
6690c83ed8eSKurt Hackel /* cluster set */
6700c83ed8eSKurt Hackel 
6710c83ed8eSKurt Hackel struct o2nm_cluster_group {
6720c83ed8eSKurt Hackel 	struct configfs_subsystem cs_subsys;
6730c83ed8eSKurt Hackel 	/* some stuff? */
6740c83ed8eSKurt Hackel };
6750c83ed8eSKurt Hackel 
6760c83ed8eSKurt Hackel #if 0
6770c83ed8eSKurt Hackel static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group)
6780c83ed8eSKurt Hackel {
6790c83ed8eSKurt Hackel 	return group ?
6800c83ed8eSKurt Hackel 		container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys)
6810c83ed8eSKurt Hackel 	       : NULL;
6820c83ed8eSKurt Hackel }
6830c83ed8eSKurt Hackel #endif
6840c83ed8eSKurt Hackel 
o2nm_cluster_group_make_group(struct config_group * group,const char * name)685f89ab861SJoel Becker static struct config_group *o2nm_cluster_group_make_group(struct config_group *group,
686f89ab861SJoel Becker 							  const char *name)
6870c83ed8eSKurt Hackel {
6880c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = NULL;
6890c83ed8eSKurt Hackel 	struct o2nm_node_group *ns = NULL;
690f89ab861SJoel Becker 	struct config_group *o2hb_group = NULL, *ret = NULL;
6910c83ed8eSKurt Hackel 
692137cebf9Shongnanli 	/* this runs under the parent dir's i_rwsem; there can be only
6930c83ed8eSKurt Hackel 	 * one caller in here at a time */
694f89ab861SJoel Becker 	if (o2nm_single_cluster)
695a6795e9eSJoel Becker 		return ERR_PTR(-ENOSPC);
6960c83ed8eSKurt Hackel 
697cd861280SRobert P. J. Day 	cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
698cd861280SRobert P. J. Day 	ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
6990c83ed8eSKurt Hackel 	o2hb_group = o2hb_alloc_hb_set();
7001ae1602dSChristoph Hellwig 	if (cluster == NULL || ns == NULL || o2hb_group == NULL)
7010c83ed8eSKurt Hackel 		goto out;
7020c83ed8eSKurt Hackel 
7030c83ed8eSKurt Hackel 	config_group_init_type_name(&cluster->cl_group, name,
7040c83ed8eSKurt Hackel 				    &o2nm_cluster_type);
7051ae1602dSChristoph Hellwig 	configfs_add_default_group(&ns->ns_group, &cluster->cl_group);
7061ae1602dSChristoph Hellwig 
7070c83ed8eSKurt Hackel 	config_group_init_type_name(&ns->ns_group, "node",
7080c83ed8eSKurt Hackel 				    &o2nm_node_group_type);
7091ae1602dSChristoph Hellwig 	configfs_add_default_group(o2hb_group, &cluster->cl_group);
7100c83ed8eSKurt Hackel 
7110c83ed8eSKurt Hackel 	rwlock_init(&cluster->cl_nodes_lock);
7120c83ed8eSKurt Hackel 	cluster->cl_node_ip_tree = RB_ROOT;
713b5dd8030SJeff Mahoney 	cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT;
714b5dd8030SJeff Mahoney 	cluster->cl_idle_timeout_ms    = O2NET_IDLE_TIMEOUT_MS_DEFAULT;
715b5dd8030SJeff Mahoney 	cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT;
716f6656d26SSunil Mushran 	cluster->cl_fence_method       = O2NM_FENCE_RESET;
7170c83ed8eSKurt Hackel 
718f89ab861SJoel Becker 	ret = &cluster->cl_group;
7190c83ed8eSKurt Hackel 	o2nm_single_cluster = cluster;
7200c83ed8eSKurt Hackel 
7210c83ed8eSKurt Hackel out:
722f89ab861SJoel Becker 	if (ret == NULL) {
7230c83ed8eSKurt Hackel 		kfree(cluster);
7240c83ed8eSKurt Hackel 		kfree(ns);
7250c83ed8eSKurt Hackel 		o2hb_free_hb_set(o2hb_group);
726a6795e9eSJoel Becker 		ret = ERR_PTR(-ENOMEM);
7270c83ed8eSKurt Hackel 	}
7280c83ed8eSKurt Hackel 
7290c83ed8eSKurt Hackel 	return ret;
7300c83ed8eSKurt Hackel }
7310c83ed8eSKurt Hackel 
o2nm_cluster_group_drop_item(struct config_group * group,struct config_item * item)7320c83ed8eSKurt Hackel static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item)
7330c83ed8eSKurt Hackel {
7340c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
7350c83ed8eSKurt Hackel 
7360c83ed8eSKurt Hackel 	BUG_ON(o2nm_single_cluster != cluster);
7370c83ed8eSKurt Hackel 	o2nm_single_cluster = NULL;
7380c83ed8eSKurt Hackel 
7391ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&cluster->cl_group);
7400c83ed8eSKurt Hackel 	config_item_put(item);
7410c83ed8eSKurt Hackel }
7420c83ed8eSKurt Hackel 
7430c83ed8eSKurt Hackel static struct configfs_group_operations o2nm_cluster_group_group_ops = {
7440c83ed8eSKurt Hackel 	.make_group	= o2nm_cluster_group_make_group,
7450c83ed8eSKurt Hackel 	.drop_item	= o2nm_cluster_group_drop_item,
7460c83ed8eSKurt Hackel };
7470c83ed8eSKurt Hackel 
7484843afe4SBhumika Goyal static const struct config_item_type o2nm_cluster_group_type = {
7490c83ed8eSKurt Hackel 	.ct_group_ops	= &o2nm_cluster_group_group_ops,
7500c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
7510c83ed8eSKurt Hackel };
7520c83ed8eSKurt Hackel 
7530c83ed8eSKurt Hackel static struct o2nm_cluster_group o2nm_cluster_group = {
7540c83ed8eSKurt Hackel 	.cs_subsys = {
7550c83ed8eSKurt Hackel 		.su_group = {
7560c83ed8eSKurt Hackel 			.cg_item = {
7570c83ed8eSKurt Hackel 				.ci_namebuf = "cluster",
7580c83ed8eSKurt Hackel 				.ci_type = &o2nm_cluster_group_type,
7590c83ed8eSKurt Hackel 			},
7600c83ed8eSKurt Hackel 		},
7610c83ed8eSKurt Hackel 	},
7620c83ed8eSKurt Hackel };
7630c83ed8eSKurt Hackel 
o2nm_lock_subsystem(void)764853bc26aSalex chen static inline void o2nm_lock_subsystem(void)
765853bc26aSalex chen {
766853bc26aSalex chen 	mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex);
767853bc26aSalex chen }
768853bc26aSalex chen 
o2nm_unlock_subsystem(void)769853bc26aSalex chen static inline void o2nm_unlock_subsystem(void)
770853bc26aSalex chen {
771853bc26aSalex chen 	mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex);
772853bc26aSalex chen }
773853bc26aSalex chen 
o2nm_depend_item(struct config_item * item)77414829422SJoel Becker int o2nm_depend_item(struct config_item *item)
77514829422SJoel Becker {
77614829422SJoel Becker 	return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
77714829422SJoel Becker }
77814829422SJoel Becker 
o2nm_undepend_item(struct config_item * item)77914829422SJoel Becker void o2nm_undepend_item(struct config_item *item)
78014829422SJoel Becker {
7819a9e3415SKrzysztof Opasiak 	configfs_undepend_item(item);
78214829422SJoel Becker }
78314829422SJoel Becker 
o2nm_depend_this_node(void)78416c6a4f2SJoel Becker int o2nm_depend_this_node(void)
78516c6a4f2SJoel Becker {
78616c6a4f2SJoel Becker 	int ret = 0;
78716c6a4f2SJoel Becker 	struct o2nm_node *local_node;
78816c6a4f2SJoel Becker 
78916c6a4f2SJoel Becker 	local_node = o2nm_get_node_by_num(o2nm_this_node());
79016c6a4f2SJoel Becker 	if (!local_node) {
79116c6a4f2SJoel Becker 		ret = -EINVAL;
79216c6a4f2SJoel Becker 		goto out;
79316c6a4f2SJoel Becker 	}
79416c6a4f2SJoel Becker 
79516c6a4f2SJoel Becker 	ret = o2nm_depend_item(&local_node->nd_item);
79616c6a4f2SJoel Becker 	o2nm_node_put(local_node);
79716c6a4f2SJoel Becker 
79816c6a4f2SJoel Becker out:
79916c6a4f2SJoel Becker 	return ret;
80016c6a4f2SJoel Becker }
80116c6a4f2SJoel Becker 
o2nm_undepend_this_node(void)80216c6a4f2SJoel Becker void o2nm_undepend_this_node(void)
80316c6a4f2SJoel Becker {
80416c6a4f2SJoel Becker 	struct o2nm_node *local_node;
80516c6a4f2SJoel Becker 
80616c6a4f2SJoel Becker 	local_node = o2nm_get_node_by_num(o2nm_this_node());
80716c6a4f2SJoel Becker 	BUG_ON(!local_node);
80816c6a4f2SJoel Becker 
80916c6a4f2SJoel Becker 	o2nm_undepend_item(&local_node->nd_item);
81016c6a4f2SJoel Becker 	o2nm_node_put(local_node);
81116c6a4f2SJoel Becker }
81216c6a4f2SJoel Becker 
81316c6a4f2SJoel Becker 
exit_o2nm(void)8140c83ed8eSKurt Hackel static void __exit exit_o2nm(void)
8150c83ed8eSKurt Hackel {
8160c83ed8eSKurt Hackel 	/* XXX sync with hb callbacks and shut down hb? */
8170c83ed8eSKurt Hackel 	o2net_unregister_hb_callbacks();
8180c83ed8eSKurt Hackel 	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
8190c83ed8eSKurt Hackel 	o2cb_sys_shutdown();
8200c83ed8eSKurt Hackel 
8210c83ed8eSKurt Hackel 	o2net_exit();
82287d3d3f3SSunil Mushran 	o2hb_exit();
8230c83ed8eSKurt Hackel }
8240c83ed8eSKurt Hackel 
init_o2nm(void)8250c83ed8eSKurt Hackel static int __init init_o2nm(void)
8260c83ed8eSKurt Hackel {
8277ed6d4e4SColin Ian King 	int ret;
8280c83ed8eSKurt Hackel 
829e581595eSGreg Kroah-Hartman 	o2hb_init();
8302309e9e0SSunil Mushran 
8312309e9e0SSunil Mushran 	ret = o2net_init();
8322309e9e0SSunil Mushran 	if (ret)
83387d3d3f3SSunil Mushran 		goto out_o2hb;
8340c83ed8eSKurt Hackel 
8350c83ed8eSKurt Hackel 	ret = o2net_register_hb_callbacks();
8360c83ed8eSKurt Hackel 	if (ret)
8373878f110SJoel Becker 		goto out_o2net;
8380c83ed8eSKurt Hackel 
8390c83ed8eSKurt Hackel 	config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
840e6bd07aeSJoel Becker 	mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex);
8410c83ed8eSKurt Hackel 	ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
8420c83ed8eSKurt Hackel 	if (ret) {
8430c83ed8eSKurt Hackel 		printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
8440c83ed8eSKurt Hackel 		goto out_callbacks;
8450c83ed8eSKurt Hackel 	}
8460c83ed8eSKurt Hackel 
8470c83ed8eSKurt Hackel 	ret = o2cb_sys_init();
8480c83ed8eSKurt Hackel 	if (!ret)
8490c83ed8eSKurt Hackel 		goto out;
8500c83ed8eSKurt Hackel 
8510c83ed8eSKurt Hackel 	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
8520c83ed8eSKurt Hackel out_callbacks:
8530c83ed8eSKurt Hackel 	o2net_unregister_hb_callbacks();
854895928b8SJeff Mahoney out_o2net:
855895928b8SJeff Mahoney 	o2net_exit();
85687d3d3f3SSunil Mushran out_o2hb:
85787d3d3f3SSunil Mushran 	o2hb_exit();
8580c83ed8eSKurt Hackel out:
8590c83ed8eSKurt Hackel 	return ret;
8600c83ed8eSKurt Hackel }
8610c83ed8eSKurt Hackel 
8620c83ed8eSKurt Hackel MODULE_AUTHOR("Oracle");
8630c83ed8eSKurt Hackel MODULE_LICENSE("GPL");
864ff8fb335SGoldwyn Rodrigues MODULE_DESCRIPTION("OCFS2 cluster management");
8650c83ed8eSKurt Hackel 
8660c83ed8eSKurt Hackel module_init(init_o2nm)
8670c83ed8eSKurt Hackel module_exit(exit_o2nm)
868