xref: /OK3568_Linux_fs/kernel/fs/ocfs2/cluster/nodemanager.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* -*- mode: c; c-basic-offset: 8; -*-
3*4882a593Smuzhiyun  * vim: noexpandtab sw=8 ts=8 sts=0:
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2004, 2005 Oracle.  All rights reserved.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/slab.h>
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/configfs.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "tcp.h"
14*4882a593Smuzhiyun #include "nodemanager.h"
15*4882a593Smuzhiyun #include "heartbeat.h"
16*4882a593Smuzhiyun #include "masklog.h"
17*4882a593Smuzhiyun #include "sys.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* for now we operate under the assertion that there can be only one
20*4882a593Smuzhiyun  * cluster active at a time.  Changing this will require trickling
21*4882a593Smuzhiyun  * cluster references throughout where nodes are looked up */
22*4882a593Smuzhiyun struct o2nm_cluster *o2nm_single_cluster = NULL;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun static const char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = {
25*4882a593Smuzhiyun 	"reset",	/* O2NM_FENCE_RESET */
26*4882a593Smuzhiyun 	"panic",	/* O2NM_FENCE_PANIC */
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun static inline void o2nm_lock_subsystem(void);
30*4882a593Smuzhiyun static inline void o2nm_unlock_subsystem(void);
31*4882a593Smuzhiyun 
o2nm_get_node_by_num(u8 node_num)32*4882a593Smuzhiyun struct o2nm_node *o2nm_get_node_by_num(u8 node_num)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	struct o2nm_node *node = NULL;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL)
37*4882a593Smuzhiyun 		goto out;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	read_lock(&o2nm_single_cluster->cl_nodes_lock);
40*4882a593Smuzhiyun 	node = o2nm_single_cluster->cl_nodes[node_num];
41*4882a593Smuzhiyun 	if (node)
42*4882a593Smuzhiyun 		config_item_get(&node->nd_item);
43*4882a593Smuzhiyun 	read_unlock(&o2nm_single_cluster->cl_nodes_lock);
44*4882a593Smuzhiyun out:
45*4882a593Smuzhiyun 	return node;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(o2nm_get_node_by_num);
48*4882a593Smuzhiyun 
o2nm_configured_node_map(unsigned long * map,unsigned bytes)49*4882a593Smuzhiyun int o2nm_configured_node_map(unsigned long *map, unsigned bytes)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = o2nm_single_cluster;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap)));
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	if (cluster == NULL)
56*4882a593Smuzhiyun 		return -EINVAL;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	read_lock(&cluster->cl_nodes_lock);
59*4882a593Smuzhiyun 	memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap));
60*4882a593Smuzhiyun 	read_unlock(&cluster->cl_nodes_lock);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	return 0;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(o2nm_configured_node_map);
65*4882a593Smuzhiyun 
o2nm_node_ip_tree_lookup(struct o2nm_cluster * cluster,__be32 ip_needle,struct rb_node *** ret_p,struct rb_node ** ret_parent)66*4882a593Smuzhiyun static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster,
67*4882a593Smuzhiyun 						  __be32 ip_needle,
68*4882a593Smuzhiyun 						  struct rb_node ***ret_p,
69*4882a593Smuzhiyun 						  struct rb_node **ret_parent)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	struct rb_node **p = &cluster->cl_node_ip_tree.rb_node;
72*4882a593Smuzhiyun 	struct rb_node *parent = NULL;
73*4882a593Smuzhiyun 	struct o2nm_node *node, *ret = NULL;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	while (*p) {
76*4882a593Smuzhiyun 		int cmp;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 		parent = *p;
79*4882a593Smuzhiyun 		node = rb_entry(parent, struct o2nm_node, nd_ip_node);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 		cmp = memcmp(&ip_needle, &node->nd_ipv4_address,
82*4882a593Smuzhiyun 				sizeof(ip_needle));
83*4882a593Smuzhiyun 		if (cmp < 0)
84*4882a593Smuzhiyun 			p = &(*p)->rb_left;
85*4882a593Smuzhiyun 		else if (cmp > 0)
86*4882a593Smuzhiyun 			p = &(*p)->rb_right;
87*4882a593Smuzhiyun 		else {
88*4882a593Smuzhiyun 			ret = node;
89*4882a593Smuzhiyun 			break;
90*4882a593Smuzhiyun 		}
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	if (ret_p != NULL)
94*4882a593Smuzhiyun 		*ret_p = p;
95*4882a593Smuzhiyun 	if (ret_parent != NULL)
96*4882a593Smuzhiyun 		*ret_parent = parent;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	return ret;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
o2nm_get_node_by_ip(__be32 addr)101*4882a593Smuzhiyun struct o2nm_node *o2nm_get_node_by_ip(__be32 addr)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	struct o2nm_node *node = NULL;
104*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = o2nm_single_cluster;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	if (cluster == NULL)
107*4882a593Smuzhiyun 		goto out;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	read_lock(&cluster->cl_nodes_lock);
110*4882a593Smuzhiyun 	node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL);
111*4882a593Smuzhiyun 	if (node)
112*4882a593Smuzhiyun 		config_item_get(&node->nd_item);
113*4882a593Smuzhiyun 	read_unlock(&cluster->cl_nodes_lock);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun out:
116*4882a593Smuzhiyun 	return node;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip);
119*4882a593Smuzhiyun 
o2nm_node_put(struct o2nm_node * node)120*4882a593Smuzhiyun void o2nm_node_put(struct o2nm_node *node)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	config_item_put(&node->nd_item);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(o2nm_node_put);
125*4882a593Smuzhiyun 
o2nm_node_get(struct o2nm_node * node)126*4882a593Smuzhiyun void o2nm_node_get(struct o2nm_node *node)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	config_item_get(&node->nd_item);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(o2nm_node_get);
131*4882a593Smuzhiyun 
o2nm_this_node(void)132*4882a593Smuzhiyun u8 o2nm_this_node(void)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	u8 node_num = O2NM_MAX_NODES;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local)
137*4882a593Smuzhiyun 		node_num = o2nm_single_cluster->cl_local_node;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	return node_num;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(o2nm_this_node);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /* node configfs bits */
144*4882a593Smuzhiyun 
to_o2nm_cluster(struct config_item * item)145*4882a593Smuzhiyun static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	return item ?
148*4882a593Smuzhiyun 		container_of(to_config_group(item), struct o2nm_cluster,
149*4882a593Smuzhiyun 			     cl_group)
150*4882a593Smuzhiyun 		: NULL;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
to_o2nm_node(struct config_item * item)153*4882a593Smuzhiyun static struct o2nm_node *to_o2nm_node(struct config_item *item)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	return item ? container_of(item, struct o2nm_node, nd_item) : NULL;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
o2nm_node_release(struct config_item * item)158*4882a593Smuzhiyun static void o2nm_node_release(struct config_item *item)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	struct o2nm_node *node = to_o2nm_node(item);
161*4882a593Smuzhiyun 	kfree(node);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
o2nm_node_num_show(struct config_item * item,char * page)164*4882a593Smuzhiyun static ssize_t o2nm_node_num_show(struct config_item *item, char *page)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	return sprintf(page, "%d\n", to_o2nm_node(item)->nd_num);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
to_o2nm_cluster_from_node(struct o2nm_node * node)169*4882a593Smuzhiyun static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	/* through the first node_set .parent
172*4882a593Smuzhiyun 	 * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */
173*4882a593Smuzhiyun 	if (node->nd_item.ci_parent)
174*4882a593Smuzhiyun 		return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent);
175*4882a593Smuzhiyun 	else
176*4882a593Smuzhiyun 		return NULL;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun enum {
180*4882a593Smuzhiyun 	O2NM_NODE_ATTR_NUM = 0,
181*4882a593Smuzhiyun 	O2NM_NODE_ATTR_PORT,
182*4882a593Smuzhiyun 	O2NM_NODE_ATTR_ADDRESS,
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun 
o2nm_node_num_store(struct config_item * item,const char * page,size_t count)185*4882a593Smuzhiyun static ssize_t o2nm_node_num_store(struct config_item *item, const char *page,
186*4882a593Smuzhiyun 				   size_t count)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	struct o2nm_node *node = to_o2nm_node(item);
189*4882a593Smuzhiyun 	struct o2nm_cluster *cluster;
190*4882a593Smuzhiyun 	unsigned long tmp;
191*4882a593Smuzhiyun 	char *p = (char *)page;
192*4882a593Smuzhiyun 	int ret = 0;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	tmp = simple_strtoul(p, &p, 0);
195*4882a593Smuzhiyun 	if (!p || (*p && (*p != '\n')))
196*4882a593Smuzhiyun 		return -EINVAL;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	if (tmp >= O2NM_MAX_NODES)
199*4882a593Smuzhiyun 		return -ERANGE;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	/* once we're in the cl_nodes tree networking can look us up by
202*4882a593Smuzhiyun 	 * node number and try to use our address and port attributes
203*4882a593Smuzhiyun 	 * to connect to this node.. make sure that they've been set
204*4882a593Smuzhiyun 	 * before writing the node attribute? */
205*4882a593Smuzhiyun 	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
206*4882a593Smuzhiyun 	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
207*4882a593Smuzhiyun 		return -EINVAL; /* XXX */
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	o2nm_lock_subsystem();
210*4882a593Smuzhiyun 	cluster = to_o2nm_cluster_from_node(node);
211*4882a593Smuzhiyun 	if (!cluster) {
212*4882a593Smuzhiyun 		o2nm_unlock_subsystem();
213*4882a593Smuzhiyun 		return -EINVAL;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	write_lock(&cluster->cl_nodes_lock);
217*4882a593Smuzhiyun 	if (cluster->cl_nodes[tmp])
218*4882a593Smuzhiyun 		ret = -EEXIST;
219*4882a593Smuzhiyun 	else if (test_and_set_bit(O2NM_NODE_ATTR_NUM,
220*4882a593Smuzhiyun 			&node->nd_set_attributes))
221*4882a593Smuzhiyun 		ret = -EBUSY;
222*4882a593Smuzhiyun 	else  {
223*4882a593Smuzhiyun 		cluster->cl_nodes[tmp] = node;
224*4882a593Smuzhiyun 		node->nd_num = tmp;
225*4882a593Smuzhiyun 		set_bit(tmp, cluster->cl_nodes_bitmap);
226*4882a593Smuzhiyun 	}
227*4882a593Smuzhiyun 	write_unlock(&cluster->cl_nodes_lock);
228*4882a593Smuzhiyun 	o2nm_unlock_subsystem();
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	if (ret)
231*4882a593Smuzhiyun 		return ret;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	return count;
234*4882a593Smuzhiyun }
o2nm_node_ipv4_port_show(struct config_item * item,char * page)235*4882a593Smuzhiyun static ssize_t o2nm_node_ipv4_port_show(struct config_item *item, char *page)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	return sprintf(page, "%u\n", ntohs(to_o2nm_node(item)->nd_ipv4_port));
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
o2nm_node_ipv4_port_store(struct config_item * item,const char * page,size_t count)240*4882a593Smuzhiyun static ssize_t o2nm_node_ipv4_port_store(struct config_item *item,
241*4882a593Smuzhiyun 					 const char *page, size_t count)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct o2nm_node *node = to_o2nm_node(item);
244*4882a593Smuzhiyun 	unsigned long tmp;
245*4882a593Smuzhiyun 	char *p = (char *)page;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	tmp = simple_strtoul(p, &p, 0);
248*4882a593Smuzhiyun 	if (!p || (*p && (*p != '\n')))
249*4882a593Smuzhiyun 		return -EINVAL;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	if (tmp == 0)
252*4882a593Smuzhiyun 		return -EINVAL;
253*4882a593Smuzhiyun 	if (tmp >= (u16)-1)
254*4882a593Smuzhiyun 		return -ERANGE;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (test_and_set_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
257*4882a593Smuzhiyun 		return -EBUSY;
258*4882a593Smuzhiyun 	node->nd_ipv4_port = htons(tmp);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	return count;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
o2nm_node_ipv4_address_show(struct config_item * item,char * page)263*4882a593Smuzhiyun static ssize_t o2nm_node_ipv4_address_show(struct config_item *item, char *page)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	return sprintf(page, "%pI4\n", &to_o2nm_node(item)->nd_ipv4_address);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
o2nm_node_ipv4_address_store(struct config_item * item,const char * page,size_t count)268*4882a593Smuzhiyun static ssize_t o2nm_node_ipv4_address_store(struct config_item *item,
269*4882a593Smuzhiyun 					    const char *page,
270*4882a593Smuzhiyun 					    size_t count)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct o2nm_node *node = to_o2nm_node(item);
273*4882a593Smuzhiyun 	struct o2nm_cluster *cluster;
274*4882a593Smuzhiyun 	int ret, i;
275*4882a593Smuzhiyun 	struct rb_node **p, *parent;
276*4882a593Smuzhiyun 	unsigned int octets[4];
277*4882a593Smuzhiyun 	__be32 ipv4_addr = 0;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2],
280*4882a593Smuzhiyun 		     &octets[1], &octets[0]);
281*4882a593Smuzhiyun 	if (ret != 4)
282*4882a593Smuzhiyun 		return -EINVAL;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(octets); i++) {
285*4882a593Smuzhiyun 		if (octets[i] > 255)
286*4882a593Smuzhiyun 			return -ERANGE;
287*4882a593Smuzhiyun 		be32_add_cpu(&ipv4_addr, octets[i] << (i * 8));
288*4882a593Smuzhiyun 	}
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	o2nm_lock_subsystem();
291*4882a593Smuzhiyun 	cluster = to_o2nm_cluster_from_node(node);
292*4882a593Smuzhiyun 	if (!cluster) {
293*4882a593Smuzhiyun 		o2nm_unlock_subsystem();
294*4882a593Smuzhiyun 		return -EINVAL;
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	ret = 0;
298*4882a593Smuzhiyun 	write_lock(&cluster->cl_nodes_lock);
299*4882a593Smuzhiyun 	if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
300*4882a593Smuzhiyun 		ret = -EEXIST;
301*4882a593Smuzhiyun 	else if (test_and_set_bit(O2NM_NODE_ATTR_ADDRESS,
302*4882a593Smuzhiyun 			&node->nd_set_attributes))
303*4882a593Smuzhiyun 		ret = -EBUSY;
304*4882a593Smuzhiyun 	else {
305*4882a593Smuzhiyun 		rb_link_node(&node->nd_ip_node, parent, p);
306*4882a593Smuzhiyun 		rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 	write_unlock(&cluster->cl_nodes_lock);
309*4882a593Smuzhiyun 	o2nm_unlock_subsystem();
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	if (ret)
312*4882a593Smuzhiyun 		return ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr));
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	return count;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
o2nm_node_local_show(struct config_item * item,char * page)319*4882a593Smuzhiyun static ssize_t o2nm_node_local_show(struct config_item *item, char *page)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	return sprintf(page, "%d\n", to_o2nm_node(item)->nd_local);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
o2nm_node_local_store(struct config_item * item,const char * page,size_t count)324*4882a593Smuzhiyun static ssize_t o2nm_node_local_store(struct config_item *item, const char *page,
325*4882a593Smuzhiyun 				     size_t count)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	struct o2nm_node *node = to_o2nm_node(item);
328*4882a593Smuzhiyun 	struct o2nm_cluster *cluster;
329*4882a593Smuzhiyun 	unsigned long tmp;
330*4882a593Smuzhiyun 	char *p = (char *)page;
331*4882a593Smuzhiyun 	ssize_t ret;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	tmp = simple_strtoul(p, &p, 0);
334*4882a593Smuzhiyun 	if (!p || (*p && (*p != '\n')))
335*4882a593Smuzhiyun 		return -EINVAL;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	tmp = !!tmp; /* boolean of whether this node wants to be local */
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	/* setting local turns on networking rx for now so we require having
340*4882a593Smuzhiyun 	 * set everything else first */
341*4882a593Smuzhiyun 	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
342*4882a593Smuzhiyun 	    !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) ||
343*4882a593Smuzhiyun 	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
344*4882a593Smuzhiyun 		return -EINVAL; /* XXX */
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	o2nm_lock_subsystem();
347*4882a593Smuzhiyun 	cluster = to_o2nm_cluster_from_node(node);
348*4882a593Smuzhiyun 	if (!cluster) {
349*4882a593Smuzhiyun 		ret = -EINVAL;
350*4882a593Smuzhiyun 		goto out;
351*4882a593Smuzhiyun 	}
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	/* the only failure case is trying to set a new local node
354*4882a593Smuzhiyun 	 * when a different one is already set */
355*4882a593Smuzhiyun 	if (tmp && tmp == cluster->cl_has_local &&
356*4882a593Smuzhiyun 	    cluster->cl_local_node != node->nd_num) {
357*4882a593Smuzhiyun 		ret = -EBUSY;
358*4882a593Smuzhiyun 		goto out;
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* bring up the rx thread if we're setting the new local node. */
362*4882a593Smuzhiyun 	if (tmp && !cluster->cl_has_local) {
363*4882a593Smuzhiyun 		ret = o2net_start_listening(node);
364*4882a593Smuzhiyun 		if (ret)
365*4882a593Smuzhiyun 			goto out;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	if (!tmp && cluster->cl_has_local &&
369*4882a593Smuzhiyun 	    cluster->cl_local_node == node->nd_num) {
370*4882a593Smuzhiyun 		o2net_stop_listening(node);
371*4882a593Smuzhiyun 		cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	node->nd_local = tmp;
375*4882a593Smuzhiyun 	if (node->nd_local) {
376*4882a593Smuzhiyun 		cluster->cl_has_local = tmp;
377*4882a593Smuzhiyun 		cluster->cl_local_node = node->nd_num;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	ret = count;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun out:
383*4882a593Smuzhiyun 	o2nm_unlock_subsystem();
384*4882a593Smuzhiyun 	return ret;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_node_, num);
388*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_node_, ipv4_port);
389*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_node_, ipv4_address);
390*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_node_, local);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static struct configfs_attribute *o2nm_node_attrs[] = {
393*4882a593Smuzhiyun 	&o2nm_node_attr_num,
394*4882a593Smuzhiyun 	&o2nm_node_attr_ipv4_port,
395*4882a593Smuzhiyun 	&o2nm_node_attr_ipv4_address,
396*4882a593Smuzhiyun 	&o2nm_node_attr_local,
397*4882a593Smuzhiyun 	NULL,
398*4882a593Smuzhiyun };
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun static struct configfs_item_operations o2nm_node_item_ops = {
401*4882a593Smuzhiyun 	.release		= o2nm_node_release,
402*4882a593Smuzhiyun };
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun static const struct config_item_type o2nm_node_type = {
405*4882a593Smuzhiyun 	.ct_item_ops	= &o2nm_node_item_ops,
406*4882a593Smuzhiyun 	.ct_attrs	= o2nm_node_attrs,
407*4882a593Smuzhiyun 	.ct_owner	= THIS_MODULE,
408*4882a593Smuzhiyun };
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun /* node set */
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun struct o2nm_node_group {
413*4882a593Smuzhiyun 	struct config_group ns_group;
414*4882a593Smuzhiyun 	/* some stuff? */
415*4882a593Smuzhiyun };
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun #if 0
418*4882a593Smuzhiyun static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	return group ?
421*4882a593Smuzhiyun 		container_of(group, struct o2nm_node_group, ns_group)
422*4882a593Smuzhiyun 		: NULL;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun #endif
425*4882a593Smuzhiyun 
o2nm_cluster_attr_write(const char * page,ssize_t count,unsigned int * val)426*4882a593Smuzhiyun static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
427*4882a593Smuzhiyun                                        unsigned int *val)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	unsigned long tmp;
430*4882a593Smuzhiyun 	char *p = (char *)page;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	tmp = simple_strtoul(p, &p, 0);
433*4882a593Smuzhiyun 	if (!p || (*p && (*p != '\n')))
434*4882a593Smuzhiyun 		return -EINVAL;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	if (tmp == 0)
437*4882a593Smuzhiyun 		return -EINVAL;
438*4882a593Smuzhiyun 	if (tmp >= (u32)-1)
439*4882a593Smuzhiyun 		return -ERANGE;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	*val = tmp;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return count;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
o2nm_cluster_idle_timeout_ms_show(struct config_item * item,char * page)446*4882a593Smuzhiyun static ssize_t o2nm_cluster_idle_timeout_ms_show(struct config_item *item,
447*4882a593Smuzhiyun 	char *page)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	return sprintf(page, "%u\n", to_o2nm_cluster(item)->cl_idle_timeout_ms);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
o2nm_cluster_idle_timeout_ms_store(struct config_item * item,const char * page,size_t count)452*4882a593Smuzhiyun static ssize_t o2nm_cluster_idle_timeout_ms_store(struct config_item *item,
453*4882a593Smuzhiyun 	const char *page, size_t count)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
456*4882a593Smuzhiyun 	ssize_t ret;
457*4882a593Smuzhiyun 	unsigned int val;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	ret =  o2nm_cluster_attr_write(page, count, &val);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	if (ret > 0) {
462*4882a593Smuzhiyun 		if (cluster->cl_idle_timeout_ms != val
463*4882a593Smuzhiyun 			&& o2net_num_connected_peers()) {
464*4882a593Smuzhiyun 			mlog(ML_NOTICE,
465*4882a593Smuzhiyun 			     "o2net: cannot change idle timeout after "
466*4882a593Smuzhiyun 			     "the first peer has agreed to it."
467*4882a593Smuzhiyun 			     "  %d connected peers\n",
468*4882a593Smuzhiyun 			     o2net_num_connected_peers());
469*4882a593Smuzhiyun 			ret = -EINVAL;
470*4882a593Smuzhiyun 		} else if (val <= cluster->cl_keepalive_delay_ms) {
471*4882a593Smuzhiyun 			mlog(ML_NOTICE, "o2net: idle timeout must be larger "
472*4882a593Smuzhiyun 			     "than keepalive delay\n");
473*4882a593Smuzhiyun 			ret = -EINVAL;
474*4882a593Smuzhiyun 		} else {
475*4882a593Smuzhiyun 			cluster->cl_idle_timeout_ms = val;
476*4882a593Smuzhiyun 		}
477*4882a593Smuzhiyun 	}
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	return ret;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
o2nm_cluster_keepalive_delay_ms_show(struct config_item * item,char * page)482*4882a593Smuzhiyun static ssize_t o2nm_cluster_keepalive_delay_ms_show(
483*4882a593Smuzhiyun 	struct config_item *item, char *page)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun 	return sprintf(page, "%u\n",
486*4882a593Smuzhiyun 			to_o2nm_cluster(item)->cl_keepalive_delay_ms);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
o2nm_cluster_keepalive_delay_ms_store(struct config_item * item,const char * page,size_t count)489*4882a593Smuzhiyun static ssize_t o2nm_cluster_keepalive_delay_ms_store(
490*4882a593Smuzhiyun 	struct config_item *item, const char *page, size_t count)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
493*4882a593Smuzhiyun 	ssize_t ret;
494*4882a593Smuzhiyun 	unsigned int val;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	ret =  o2nm_cluster_attr_write(page, count, &val);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	if (ret > 0) {
499*4882a593Smuzhiyun 		if (cluster->cl_keepalive_delay_ms != val
500*4882a593Smuzhiyun 		    && o2net_num_connected_peers()) {
501*4882a593Smuzhiyun 			mlog(ML_NOTICE,
502*4882a593Smuzhiyun 			     "o2net: cannot change keepalive delay after"
503*4882a593Smuzhiyun 			     " the first peer has agreed to it."
504*4882a593Smuzhiyun 			     "  %d connected peers\n",
505*4882a593Smuzhiyun 			     o2net_num_connected_peers());
506*4882a593Smuzhiyun 			ret = -EINVAL;
507*4882a593Smuzhiyun 		} else if (val >= cluster->cl_idle_timeout_ms) {
508*4882a593Smuzhiyun 			mlog(ML_NOTICE, "o2net: keepalive delay must be "
509*4882a593Smuzhiyun 			     "smaller than idle timeout\n");
510*4882a593Smuzhiyun 			ret = -EINVAL;
511*4882a593Smuzhiyun 		} else {
512*4882a593Smuzhiyun 			cluster->cl_keepalive_delay_ms = val;
513*4882a593Smuzhiyun 		}
514*4882a593Smuzhiyun 	}
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	return ret;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun 
o2nm_cluster_reconnect_delay_ms_show(struct config_item * item,char * page)519*4882a593Smuzhiyun static ssize_t o2nm_cluster_reconnect_delay_ms_show(
520*4882a593Smuzhiyun 	struct config_item *item, char *page)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun 	return sprintf(page, "%u\n",
523*4882a593Smuzhiyun 			to_o2nm_cluster(item)->cl_reconnect_delay_ms);
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun 
o2nm_cluster_reconnect_delay_ms_store(struct config_item * item,const char * page,size_t count)526*4882a593Smuzhiyun static ssize_t o2nm_cluster_reconnect_delay_ms_store(
527*4882a593Smuzhiyun 	struct config_item *item, const char *page, size_t count)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	return o2nm_cluster_attr_write(page, count,
530*4882a593Smuzhiyun                                &to_o2nm_cluster(item)->cl_reconnect_delay_ms);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
o2nm_cluster_fence_method_show(struct config_item * item,char * page)533*4882a593Smuzhiyun static ssize_t o2nm_cluster_fence_method_show(
534*4882a593Smuzhiyun 	struct config_item *item, char *page)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
537*4882a593Smuzhiyun 	ssize_t ret = 0;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	if (cluster)
540*4882a593Smuzhiyun 		ret = sprintf(page, "%s\n",
541*4882a593Smuzhiyun 			      o2nm_fence_method_desc[cluster->cl_fence_method]);
542*4882a593Smuzhiyun 	return ret;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun 
o2nm_cluster_fence_method_store(struct config_item * item,const char * page,size_t count)545*4882a593Smuzhiyun static ssize_t o2nm_cluster_fence_method_store(
546*4882a593Smuzhiyun 	struct config_item *item, const char *page, size_t count)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun 	unsigned int i;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	if (page[count - 1] != '\n')
551*4882a593Smuzhiyun 		goto bail;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	for (i = 0; i < O2NM_FENCE_METHODS; ++i) {
554*4882a593Smuzhiyun 		if (count != strlen(o2nm_fence_method_desc[i]) + 1)
555*4882a593Smuzhiyun 			continue;
556*4882a593Smuzhiyun 		if (strncasecmp(page, o2nm_fence_method_desc[i], count - 1))
557*4882a593Smuzhiyun 			continue;
558*4882a593Smuzhiyun 		if (to_o2nm_cluster(item)->cl_fence_method != i) {
559*4882a593Smuzhiyun 			printk(KERN_INFO "ocfs2: Changing fence method to %s\n",
560*4882a593Smuzhiyun 			       o2nm_fence_method_desc[i]);
561*4882a593Smuzhiyun 			to_o2nm_cluster(item)->cl_fence_method = i;
562*4882a593Smuzhiyun 		}
563*4882a593Smuzhiyun 		return count;
564*4882a593Smuzhiyun 	}
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun bail:
567*4882a593Smuzhiyun 	return -EINVAL;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_cluster_, idle_timeout_ms);
571*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_cluster_, keepalive_delay_ms);
572*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_cluster_, reconnect_delay_ms);
573*4882a593Smuzhiyun CONFIGFS_ATTR(o2nm_cluster_, fence_method);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun static struct configfs_attribute *o2nm_cluster_attrs[] = {
576*4882a593Smuzhiyun 	&o2nm_cluster_attr_idle_timeout_ms,
577*4882a593Smuzhiyun 	&o2nm_cluster_attr_keepalive_delay_ms,
578*4882a593Smuzhiyun 	&o2nm_cluster_attr_reconnect_delay_ms,
579*4882a593Smuzhiyun 	&o2nm_cluster_attr_fence_method,
580*4882a593Smuzhiyun 	NULL,
581*4882a593Smuzhiyun };
582*4882a593Smuzhiyun 
o2nm_node_group_make_item(struct config_group * group,const char * name)583*4882a593Smuzhiyun static struct config_item *o2nm_node_group_make_item(struct config_group *group,
584*4882a593Smuzhiyun 						     const char *name)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun 	struct o2nm_node *node = NULL;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if (strlen(name) > O2NM_MAX_NAME_LEN)
589*4882a593Smuzhiyun 		return ERR_PTR(-ENAMETOOLONG);
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
592*4882a593Smuzhiyun 	if (node == NULL)
593*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
596*4882a593Smuzhiyun 	config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
597*4882a593Smuzhiyun 	spin_lock_init(&node->nd_lock);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name);
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	return &node->nd_item;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun 
o2nm_node_group_drop_item(struct config_group * group,struct config_item * item)604*4882a593Smuzhiyun static void o2nm_node_group_drop_item(struct config_group *group,
605*4882a593Smuzhiyun 				      struct config_item *item)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun 	struct o2nm_node *node = to_o2nm_node(item);
608*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	if (cluster->cl_nodes[node->nd_num] == node) {
611*4882a593Smuzhiyun 		o2net_disconnect_node(node);
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 		if (cluster->cl_has_local &&
614*4882a593Smuzhiyun 		    (cluster->cl_local_node == node->nd_num)) {
615*4882a593Smuzhiyun 			cluster->cl_has_local = 0;
616*4882a593Smuzhiyun 			cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
617*4882a593Smuzhiyun 			o2net_stop_listening(node);
618*4882a593Smuzhiyun 		}
619*4882a593Smuzhiyun 	}
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	/* XXX call into net to stop this node from trading messages */
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	write_lock(&cluster->cl_nodes_lock);
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	/* XXX sloppy */
626*4882a593Smuzhiyun 	if (node->nd_ipv4_address)
627*4882a593Smuzhiyun 		rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree);
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	/* nd_num might be 0 if the node number hasn't been set.. */
630*4882a593Smuzhiyun 	if (cluster->cl_nodes[node->nd_num] == node) {
631*4882a593Smuzhiyun 		cluster->cl_nodes[node->nd_num] = NULL;
632*4882a593Smuzhiyun 		clear_bit(node->nd_num, cluster->cl_nodes_bitmap);
633*4882a593Smuzhiyun 	}
634*4882a593Smuzhiyun 	write_unlock(&cluster->cl_nodes_lock);
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n",
637*4882a593Smuzhiyun 	     config_item_name(&node->nd_item));
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	config_item_put(item);
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun static struct configfs_group_operations o2nm_node_group_group_ops = {
643*4882a593Smuzhiyun 	.make_item	= o2nm_node_group_make_item,
644*4882a593Smuzhiyun 	.drop_item	= o2nm_node_group_drop_item,
645*4882a593Smuzhiyun };
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun static const struct config_item_type o2nm_node_group_type = {
648*4882a593Smuzhiyun 	.ct_group_ops	= &o2nm_node_group_group_ops,
649*4882a593Smuzhiyun 	.ct_owner	= THIS_MODULE,
650*4882a593Smuzhiyun };
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun /* cluster */
653*4882a593Smuzhiyun 
o2nm_cluster_release(struct config_item * item)654*4882a593Smuzhiyun static void o2nm_cluster_release(struct config_item *item)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	kfree(cluster);
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun static struct configfs_item_operations o2nm_cluster_item_ops = {
662*4882a593Smuzhiyun 	.release	= o2nm_cluster_release,
663*4882a593Smuzhiyun };
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun static const struct config_item_type o2nm_cluster_type = {
666*4882a593Smuzhiyun 	.ct_item_ops	= &o2nm_cluster_item_ops,
667*4882a593Smuzhiyun 	.ct_attrs	= o2nm_cluster_attrs,
668*4882a593Smuzhiyun 	.ct_owner	= THIS_MODULE,
669*4882a593Smuzhiyun };
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun /* cluster set */
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun struct o2nm_cluster_group {
674*4882a593Smuzhiyun 	struct configfs_subsystem cs_subsys;
675*4882a593Smuzhiyun 	/* some stuff? */
676*4882a593Smuzhiyun };
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun #if 0
679*4882a593Smuzhiyun static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group)
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun 	return group ?
682*4882a593Smuzhiyun 		container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys)
683*4882a593Smuzhiyun 	       : NULL;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun #endif
686*4882a593Smuzhiyun 
o2nm_cluster_group_make_group(struct config_group * group,const char * name)687*4882a593Smuzhiyun static struct config_group *o2nm_cluster_group_make_group(struct config_group *group,
688*4882a593Smuzhiyun 							  const char *name)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = NULL;
691*4882a593Smuzhiyun 	struct o2nm_node_group *ns = NULL;
692*4882a593Smuzhiyun 	struct config_group *o2hb_group = NULL, *ret = NULL;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	/* this runs under the parent dir's i_mutex; there can be only
695*4882a593Smuzhiyun 	 * one caller in here at a time */
696*4882a593Smuzhiyun 	if (o2nm_single_cluster)
697*4882a593Smuzhiyun 		return ERR_PTR(-ENOSPC);
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
700*4882a593Smuzhiyun 	ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
701*4882a593Smuzhiyun 	o2hb_group = o2hb_alloc_hb_set();
702*4882a593Smuzhiyun 	if (cluster == NULL || ns == NULL || o2hb_group == NULL)
703*4882a593Smuzhiyun 		goto out;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	config_group_init_type_name(&cluster->cl_group, name,
706*4882a593Smuzhiyun 				    &o2nm_cluster_type);
707*4882a593Smuzhiyun 	configfs_add_default_group(&ns->ns_group, &cluster->cl_group);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	config_group_init_type_name(&ns->ns_group, "node",
710*4882a593Smuzhiyun 				    &o2nm_node_group_type);
711*4882a593Smuzhiyun 	configfs_add_default_group(o2hb_group, &cluster->cl_group);
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	rwlock_init(&cluster->cl_nodes_lock);
714*4882a593Smuzhiyun 	cluster->cl_node_ip_tree = RB_ROOT;
715*4882a593Smuzhiyun 	cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT;
716*4882a593Smuzhiyun 	cluster->cl_idle_timeout_ms    = O2NET_IDLE_TIMEOUT_MS_DEFAULT;
717*4882a593Smuzhiyun 	cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT;
718*4882a593Smuzhiyun 	cluster->cl_fence_method       = O2NM_FENCE_RESET;
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	ret = &cluster->cl_group;
721*4882a593Smuzhiyun 	o2nm_single_cluster = cluster;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun out:
724*4882a593Smuzhiyun 	if (ret == NULL) {
725*4882a593Smuzhiyun 		kfree(cluster);
726*4882a593Smuzhiyun 		kfree(ns);
727*4882a593Smuzhiyun 		o2hb_free_hb_set(o2hb_group);
728*4882a593Smuzhiyun 		ret = ERR_PTR(-ENOMEM);
729*4882a593Smuzhiyun 	}
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	return ret;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun 
o2nm_cluster_group_drop_item(struct config_group * group,struct config_item * item)734*4882a593Smuzhiyun static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	BUG_ON(o2nm_single_cluster != cluster);
739*4882a593Smuzhiyun 	o2nm_single_cluster = NULL;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	configfs_remove_default_groups(&cluster->cl_group);
742*4882a593Smuzhiyun 	config_item_put(item);
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun static struct configfs_group_operations o2nm_cluster_group_group_ops = {
746*4882a593Smuzhiyun 	.make_group	= o2nm_cluster_group_make_group,
747*4882a593Smuzhiyun 	.drop_item	= o2nm_cluster_group_drop_item,
748*4882a593Smuzhiyun };
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun static const struct config_item_type o2nm_cluster_group_type = {
751*4882a593Smuzhiyun 	.ct_group_ops	= &o2nm_cluster_group_group_ops,
752*4882a593Smuzhiyun 	.ct_owner	= THIS_MODULE,
753*4882a593Smuzhiyun };
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun static struct o2nm_cluster_group o2nm_cluster_group = {
756*4882a593Smuzhiyun 	.cs_subsys = {
757*4882a593Smuzhiyun 		.su_group = {
758*4882a593Smuzhiyun 			.cg_item = {
759*4882a593Smuzhiyun 				.ci_namebuf = "cluster",
760*4882a593Smuzhiyun 				.ci_type = &o2nm_cluster_group_type,
761*4882a593Smuzhiyun 			},
762*4882a593Smuzhiyun 		},
763*4882a593Smuzhiyun 	},
764*4882a593Smuzhiyun };
765*4882a593Smuzhiyun 
o2nm_lock_subsystem(void)766*4882a593Smuzhiyun static inline void o2nm_lock_subsystem(void)
767*4882a593Smuzhiyun {
768*4882a593Smuzhiyun 	mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex);
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun 
o2nm_unlock_subsystem(void)771*4882a593Smuzhiyun static inline void o2nm_unlock_subsystem(void)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun 	mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex);
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun 
o2nm_depend_item(struct config_item * item)776*4882a593Smuzhiyun int o2nm_depend_item(struct config_item *item)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun 	return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun 
o2nm_undepend_item(struct config_item * item)781*4882a593Smuzhiyun void o2nm_undepend_item(struct config_item *item)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun 	configfs_undepend_item(item);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun 
o2nm_depend_this_node(void)786*4882a593Smuzhiyun int o2nm_depend_this_node(void)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun 	int ret = 0;
789*4882a593Smuzhiyun 	struct o2nm_node *local_node;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	local_node = o2nm_get_node_by_num(o2nm_this_node());
792*4882a593Smuzhiyun 	if (!local_node) {
793*4882a593Smuzhiyun 		ret = -EINVAL;
794*4882a593Smuzhiyun 		goto out;
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	ret = o2nm_depend_item(&local_node->nd_item);
798*4882a593Smuzhiyun 	o2nm_node_put(local_node);
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun out:
801*4882a593Smuzhiyun 	return ret;
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun 
o2nm_undepend_this_node(void)804*4882a593Smuzhiyun void o2nm_undepend_this_node(void)
805*4882a593Smuzhiyun {
806*4882a593Smuzhiyun 	struct o2nm_node *local_node;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	local_node = o2nm_get_node_by_num(o2nm_this_node());
809*4882a593Smuzhiyun 	BUG_ON(!local_node);
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	o2nm_undepend_item(&local_node->nd_item);
812*4882a593Smuzhiyun 	o2nm_node_put(local_node);
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 
exit_o2nm(void)816*4882a593Smuzhiyun static void __exit exit_o2nm(void)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun 	/* XXX sync with hb callbacks and shut down hb? */
819*4882a593Smuzhiyun 	o2net_unregister_hb_callbacks();
820*4882a593Smuzhiyun 	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
821*4882a593Smuzhiyun 	o2cb_sys_shutdown();
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	o2net_exit();
824*4882a593Smuzhiyun 	o2hb_exit();
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun 
init_o2nm(void)827*4882a593Smuzhiyun static int __init init_o2nm(void)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun 	int ret = -1;
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	o2hb_init();
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	ret = o2net_init();
834*4882a593Smuzhiyun 	if (ret)
835*4882a593Smuzhiyun 		goto out_o2hb;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	ret = o2net_register_hb_callbacks();
838*4882a593Smuzhiyun 	if (ret)
839*4882a593Smuzhiyun 		goto out_o2net;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
842*4882a593Smuzhiyun 	mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex);
843*4882a593Smuzhiyun 	ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
844*4882a593Smuzhiyun 	if (ret) {
845*4882a593Smuzhiyun 		printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
846*4882a593Smuzhiyun 		goto out_callbacks;
847*4882a593Smuzhiyun 	}
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	ret = o2cb_sys_init();
850*4882a593Smuzhiyun 	if (!ret)
851*4882a593Smuzhiyun 		goto out;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
854*4882a593Smuzhiyun out_callbacks:
855*4882a593Smuzhiyun 	o2net_unregister_hb_callbacks();
856*4882a593Smuzhiyun out_o2net:
857*4882a593Smuzhiyun 	o2net_exit();
858*4882a593Smuzhiyun out_o2hb:
859*4882a593Smuzhiyun 	o2hb_exit();
860*4882a593Smuzhiyun out:
861*4882a593Smuzhiyun 	return ret;
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun MODULE_AUTHOR("Oracle");
865*4882a593Smuzhiyun MODULE_LICENSE("GPL");
866*4882a593Smuzhiyun MODULE_DESCRIPTION("OCFS2 cluster management");
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun module_init(init_o2nm)
869*4882a593Smuzhiyun module_exit(exit_o2nm)
870