xref: /openbmc/linux/fs/ocfs2/cluster/nodemanager.c (revision 0c83ed8eeb28a045cdbd0b216679938aa9e665fe)
1*0c83ed8eSKurt Hackel /* -*- mode: c; c-basic-offset: 8; -*-
2*0c83ed8eSKurt Hackel  * vim: noexpandtab sw=8 ts=8 sts=0:
3*0c83ed8eSKurt Hackel  *
4*0c83ed8eSKurt Hackel  * Copyright (C) 2004, 2005 Oracle.  All rights reserved.
5*0c83ed8eSKurt Hackel  *
6*0c83ed8eSKurt Hackel  * This program is free software; you can redistribute it and/or
7*0c83ed8eSKurt Hackel  * modify it under the terms of the GNU General Public
8*0c83ed8eSKurt Hackel  * License as published by the Free Software Foundation; either
9*0c83ed8eSKurt Hackel  * version 2 of the License, or (at your option) any later version.
10*0c83ed8eSKurt Hackel  *
11*0c83ed8eSKurt Hackel  * This program is distributed in the hope that it will be useful,
12*0c83ed8eSKurt Hackel  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*0c83ed8eSKurt Hackel  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*0c83ed8eSKurt Hackel  * General Public License for more details.
15*0c83ed8eSKurt Hackel  *
16*0c83ed8eSKurt Hackel  * You should have received a copy of the GNU General Public
17*0c83ed8eSKurt Hackel  * License along with this program; if not, write to the
18*0c83ed8eSKurt Hackel  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19*0c83ed8eSKurt Hackel  * Boston, MA 021110-1307, USA.
20*0c83ed8eSKurt Hackel  */
21*0c83ed8eSKurt Hackel 
22*0c83ed8eSKurt Hackel #include <linux/kernel.h>
23*0c83ed8eSKurt Hackel #include <linux/module.h>
24*0c83ed8eSKurt Hackel #include <linux/sysctl.h>
25*0c83ed8eSKurt Hackel #include <linux/configfs.h>
26*0c83ed8eSKurt Hackel 
27*0c83ed8eSKurt Hackel #include "endian.h"
28*0c83ed8eSKurt Hackel #include "tcp.h"
29*0c83ed8eSKurt Hackel #include "nodemanager.h"
30*0c83ed8eSKurt Hackel #include "heartbeat.h"
31*0c83ed8eSKurt Hackel #include "masklog.h"
32*0c83ed8eSKurt Hackel #include "sys.h"
33*0c83ed8eSKurt Hackel #include "ver.h"
34*0c83ed8eSKurt Hackel 
35*0c83ed8eSKurt Hackel /* for now we operate under the assertion that there can be only one
36*0c83ed8eSKurt Hackel  * cluster active at a time.  Changing this will require trickling
37*0c83ed8eSKurt Hackel  * cluster references throughout where nodes are looked up */
38*0c83ed8eSKurt Hackel static struct o2nm_cluster *o2nm_single_cluster = NULL;
39*0c83ed8eSKurt Hackel 
40*0c83ed8eSKurt Hackel #define OCFS2_MAX_HB_CTL_PATH 256
41*0c83ed8eSKurt Hackel static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";
42*0c83ed8eSKurt Hackel 
43*0c83ed8eSKurt Hackel static ctl_table ocfs2_nm_table[] = {
44*0c83ed8eSKurt Hackel 	{
45*0c83ed8eSKurt Hackel 		.ctl_name	= 1,
46*0c83ed8eSKurt Hackel 		.procname	= "hb_ctl_path",
47*0c83ed8eSKurt Hackel 		.data		= ocfs2_hb_ctl_path,
48*0c83ed8eSKurt Hackel 		.maxlen		= OCFS2_MAX_HB_CTL_PATH,
49*0c83ed8eSKurt Hackel 		.mode		= 0644,
50*0c83ed8eSKurt Hackel 		.proc_handler	= &proc_dostring,
51*0c83ed8eSKurt Hackel 		.strategy	= &sysctl_string,
52*0c83ed8eSKurt Hackel 	},
53*0c83ed8eSKurt Hackel 	{ .ctl_name = 0 }
54*0c83ed8eSKurt Hackel };
55*0c83ed8eSKurt Hackel 
56*0c83ed8eSKurt Hackel static ctl_table ocfs2_mod_table[] = {
57*0c83ed8eSKurt Hackel 	{
58*0c83ed8eSKurt Hackel 		.ctl_name	= KERN_OCFS2_NM,
59*0c83ed8eSKurt Hackel 		.procname	= "nm",
60*0c83ed8eSKurt Hackel 		.data		= NULL,
61*0c83ed8eSKurt Hackel 		.maxlen		= 0,
62*0c83ed8eSKurt Hackel 		.mode		= 0555,
63*0c83ed8eSKurt Hackel 		.child		= ocfs2_nm_table
64*0c83ed8eSKurt Hackel 	},
65*0c83ed8eSKurt Hackel 	{ .ctl_name = 0}
66*0c83ed8eSKurt Hackel };
67*0c83ed8eSKurt Hackel 
68*0c83ed8eSKurt Hackel static ctl_table ocfs2_kern_table[] = {
69*0c83ed8eSKurt Hackel 	{
70*0c83ed8eSKurt Hackel 		.ctl_name	= KERN_OCFS2,
71*0c83ed8eSKurt Hackel 		.procname	= "ocfs2",
72*0c83ed8eSKurt Hackel 		.data		= NULL,
73*0c83ed8eSKurt Hackel 		.maxlen		= 0,
74*0c83ed8eSKurt Hackel 		.mode		= 0555,
75*0c83ed8eSKurt Hackel 		.child		= ocfs2_mod_table
76*0c83ed8eSKurt Hackel 	},
77*0c83ed8eSKurt Hackel 	{ .ctl_name = 0}
78*0c83ed8eSKurt Hackel };
79*0c83ed8eSKurt Hackel 
80*0c83ed8eSKurt Hackel static ctl_table ocfs2_root_table[] = {
81*0c83ed8eSKurt Hackel 	{
82*0c83ed8eSKurt Hackel 		.ctl_name	= CTL_FS,
83*0c83ed8eSKurt Hackel 		.procname	= "fs",
84*0c83ed8eSKurt Hackel 		.data		= NULL,
85*0c83ed8eSKurt Hackel 		.maxlen		= 0,
86*0c83ed8eSKurt Hackel 		.mode		= 0555,
87*0c83ed8eSKurt Hackel 		.child		= ocfs2_kern_table
88*0c83ed8eSKurt Hackel 	},
89*0c83ed8eSKurt Hackel 	{ .ctl_name = 0 }
90*0c83ed8eSKurt Hackel };
91*0c83ed8eSKurt Hackel 
92*0c83ed8eSKurt Hackel static struct ctl_table_header *ocfs2_table_header = NULL;
93*0c83ed8eSKurt Hackel 
94*0c83ed8eSKurt Hackel const char *o2nm_get_hb_ctl_path(void)
95*0c83ed8eSKurt Hackel {
96*0c83ed8eSKurt Hackel 	return ocfs2_hb_ctl_path;
97*0c83ed8eSKurt Hackel }
98*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_hb_ctl_path);
99*0c83ed8eSKurt Hackel 
100*0c83ed8eSKurt Hackel struct o2nm_cluster {
101*0c83ed8eSKurt Hackel 	struct config_group	cl_group;
102*0c83ed8eSKurt Hackel 	unsigned		cl_has_local:1;
103*0c83ed8eSKurt Hackel 	u8			cl_local_node;
104*0c83ed8eSKurt Hackel 	rwlock_t		cl_nodes_lock;
105*0c83ed8eSKurt Hackel 	struct o2nm_node  	*cl_nodes[O2NM_MAX_NODES];
106*0c83ed8eSKurt Hackel 	struct rb_root		cl_node_ip_tree;
107*0c83ed8eSKurt Hackel 	/* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */
108*0c83ed8eSKurt Hackel 	unsigned long	cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
109*0c83ed8eSKurt Hackel };
110*0c83ed8eSKurt Hackel 
111*0c83ed8eSKurt Hackel struct o2nm_node *o2nm_get_node_by_num(u8 node_num)
112*0c83ed8eSKurt Hackel {
113*0c83ed8eSKurt Hackel 	struct o2nm_node *node = NULL;
114*0c83ed8eSKurt Hackel 
115*0c83ed8eSKurt Hackel 	if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL)
116*0c83ed8eSKurt Hackel 		goto out;
117*0c83ed8eSKurt Hackel 
118*0c83ed8eSKurt Hackel 	read_lock(&o2nm_single_cluster->cl_nodes_lock);
119*0c83ed8eSKurt Hackel 	node = o2nm_single_cluster->cl_nodes[node_num];
120*0c83ed8eSKurt Hackel 	if (node)
121*0c83ed8eSKurt Hackel 		config_item_get(&node->nd_item);
122*0c83ed8eSKurt Hackel 	read_unlock(&o2nm_single_cluster->cl_nodes_lock);
123*0c83ed8eSKurt Hackel out:
124*0c83ed8eSKurt Hackel 	return node;
125*0c83ed8eSKurt Hackel }
126*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_node_by_num);
127*0c83ed8eSKurt Hackel 
128*0c83ed8eSKurt Hackel int o2nm_configured_node_map(unsigned long *map, unsigned bytes)
129*0c83ed8eSKurt Hackel {
130*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = o2nm_single_cluster;
131*0c83ed8eSKurt Hackel 
132*0c83ed8eSKurt Hackel 	BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap)));
133*0c83ed8eSKurt Hackel 
134*0c83ed8eSKurt Hackel 	if (cluster == NULL)
135*0c83ed8eSKurt Hackel 		return -EINVAL;
136*0c83ed8eSKurt Hackel 
137*0c83ed8eSKurt Hackel 	read_lock(&cluster->cl_nodes_lock);
138*0c83ed8eSKurt Hackel 	memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap));
139*0c83ed8eSKurt Hackel 	read_unlock(&cluster->cl_nodes_lock);
140*0c83ed8eSKurt Hackel 
141*0c83ed8eSKurt Hackel 	return 0;
142*0c83ed8eSKurt Hackel }
143*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_configured_node_map);
144*0c83ed8eSKurt Hackel 
145*0c83ed8eSKurt Hackel static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster,
146*0c83ed8eSKurt Hackel 						  __be32 ip_needle,
147*0c83ed8eSKurt Hackel 						  struct rb_node ***ret_p,
148*0c83ed8eSKurt Hackel 						  struct rb_node **ret_parent)
149*0c83ed8eSKurt Hackel {
150*0c83ed8eSKurt Hackel 	struct rb_node **p = &cluster->cl_node_ip_tree.rb_node;
151*0c83ed8eSKurt Hackel 	struct rb_node *parent = NULL;
152*0c83ed8eSKurt Hackel 	struct o2nm_node *node, *ret = NULL;
153*0c83ed8eSKurt Hackel 
154*0c83ed8eSKurt Hackel 	while (*p) {
155*0c83ed8eSKurt Hackel 		parent = *p;
156*0c83ed8eSKurt Hackel 		node = rb_entry(parent, struct o2nm_node, nd_ip_node);
157*0c83ed8eSKurt Hackel 
158*0c83ed8eSKurt Hackel 		if (memcmp(&ip_needle, &node->nd_ipv4_address,
159*0c83ed8eSKurt Hackel 		           sizeof(ip_needle)) < 0)
160*0c83ed8eSKurt Hackel 			p = &(*p)->rb_left;
161*0c83ed8eSKurt Hackel 		else if (memcmp(&ip_needle, &node->nd_ipv4_address,
162*0c83ed8eSKurt Hackel 			        sizeof(ip_needle)) > 0)
163*0c83ed8eSKurt Hackel 			p = &(*p)->rb_right;
164*0c83ed8eSKurt Hackel 		else {
165*0c83ed8eSKurt Hackel 			ret = node;
166*0c83ed8eSKurt Hackel 			break;
167*0c83ed8eSKurt Hackel 		}
168*0c83ed8eSKurt Hackel 	}
169*0c83ed8eSKurt Hackel 
170*0c83ed8eSKurt Hackel 	if (ret_p != NULL)
171*0c83ed8eSKurt Hackel 		*ret_p = p;
172*0c83ed8eSKurt Hackel 	if (ret_parent != NULL)
173*0c83ed8eSKurt Hackel 		*ret_parent = parent;
174*0c83ed8eSKurt Hackel 
175*0c83ed8eSKurt Hackel 	return ret;
176*0c83ed8eSKurt Hackel }
177*0c83ed8eSKurt Hackel 
178*0c83ed8eSKurt Hackel struct o2nm_node *o2nm_get_node_by_ip(__be32 addr)
179*0c83ed8eSKurt Hackel {
180*0c83ed8eSKurt Hackel 	struct o2nm_node *node = NULL;
181*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = o2nm_single_cluster;
182*0c83ed8eSKurt Hackel 
183*0c83ed8eSKurt Hackel 	if (cluster == NULL)
184*0c83ed8eSKurt Hackel 		goto out;
185*0c83ed8eSKurt Hackel 
186*0c83ed8eSKurt Hackel 	read_lock(&cluster->cl_nodes_lock);
187*0c83ed8eSKurt Hackel 	node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL);
188*0c83ed8eSKurt Hackel 	if (node)
189*0c83ed8eSKurt Hackel 		config_item_get(&node->nd_item);
190*0c83ed8eSKurt Hackel 	read_unlock(&cluster->cl_nodes_lock);
191*0c83ed8eSKurt Hackel 
192*0c83ed8eSKurt Hackel out:
193*0c83ed8eSKurt Hackel 	return node;
194*0c83ed8eSKurt Hackel }
195*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip);
196*0c83ed8eSKurt Hackel 
197*0c83ed8eSKurt Hackel void o2nm_node_put(struct o2nm_node *node)
198*0c83ed8eSKurt Hackel {
199*0c83ed8eSKurt Hackel 	config_item_put(&node->nd_item);
200*0c83ed8eSKurt Hackel }
201*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_node_put);
202*0c83ed8eSKurt Hackel 
203*0c83ed8eSKurt Hackel void o2nm_node_get(struct o2nm_node *node)
204*0c83ed8eSKurt Hackel {
205*0c83ed8eSKurt Hackel 	config_item_get(&node->nd_item);
206*0c83ed8eSKurt Hackel }
207*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_node_get);
208*0c83ed8eSKurt Hackel 
209*0c83ed8eSKurt Hackel u8 o2nm_this_node(void)
210*0c83ed8eSKurt Hackel {
211*0c83ed8eSKurt Hackel 	u8 node_num = O2NM_MAX_NODES;
212*0c83ed8eSKurt Hackel 
213*0c83ed8eSKurt Hackel 	if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local)
214*0c83ed8eSKurt Hackel 		node_num = o2nm_single_cluster->cl_local_node;
215*0c83ed8eSKurt Hackel 
216*0c83ed8eSKurt Hackel 	return node_num;
217*0c83ed8eSKurt Hackel }
218*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_this_node);
219*0c83ed8eSKurt Hackel 
220*0c83ed8eSKurt Hackel /* node configfs bits */
221*0c83ed8eSKurt Hackel 
222*0c83ed8eSKurt Hackel static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item)
223*0c83ed8eSKurt Hackel {
224*0c83ed8eSKurt Hackel 	return item ?
225*0c83ed8eSKurt Hackel 		container_of(to_config_group(item), struct o2nm_cluster,
226*0c83ed8eSKurt Hackel 			     cl_group)
227*0c83ed8eSKurt Hackel 		: NULL;
228*0c83ed8eSKurt Hackel }
229*0c83ed8eSKurt Hackel 
230*0c83ed8eSKurt Hackel static struct o2nm_node *to_o2nm_node(struct config_item *item)
231*0c83ed8eSKurt Hackel {
232*0c83ed8eSKurt Hackel 	return item ? container_of(item, struct o2nm_node, nd_item) : NULL;
233*0c83ed8eSKurt Hackel }
234*0c83ed8eSKurt Hackel 
235*0c83ed8eSKurt Hackel static void o2nm_node_release(struct config_item *item)
236*0c83ed8eSKurt Hackel {
237*0c83ed8eSKurt Hackel 	struct o2nm_node *node = to_o2nm_node(item);
238*0c83ed8eSKurt Hackel 	kfree(node);
239*0c83ed8eSKurt Hackel }
240*0c83ed8eSKurt Hackel 
241*0c83ed8eSKurt Hackel static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page)
242*0c83ed8eSKurt Hackel {
243*0c83ed8eSKurt Hackel 	return sprintf(page, "%d\n", node->nd_num);
244*0c83ed8eSKurt Hackel }
245*0c83ed8eSKurt Hackel 
246*0c83ed8eSKurt Hackel static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node)
247*0c83ed8eSKurt Hackel {
248*0c83ed8eSKurt Hackel 	/* through the first node_set .parent
249*0c83ed8eSKurt Hackel 	 * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */
250*0c83ed8eSKurt Hackel 	return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent);
251*0c83ed8eSKurt Hackel }
252*0c83ed8eSKurt Hackel 
253*0c83ed8eSKurt Hackel enum {
254*0c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_NUM = 0,
255*0c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_PORT,
256*0c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_ADDRESS,
257*0c83ed8eSKurt Hackel 	O2NM_NODE_ATTR_LOCAL,
258*0c83ed8eSKurt Hackel };
259*0c83ed8eSKurt Hackel 
260*0c83ed8eSKurt Hackel static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
261*0c83ed8eSKurt Hackel 				   size_t count)
262*0c83ed8eSKurt Hackel {
263*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
264*0c83ed8eSKurt Hackel 	unsigned long tmp;
265*0c83ed8eSKurt Hackel 	char *p = (char *)page;
266*0c83ed8eSKurt Hackel 
267*0c83ed8eSKurt Hackel 	tmp = simple_strtoul(p, &p, 0);
268*0c83ed8eSKurt Hackel 	if (!p || (*p && (*p != '\n')))
269*0c83ed8eSKurt Hackel 		return -EINVAL;
270*0c83ed8eSKurt Hackel 
271*0c83ed8eSKurt Hackel 	if (tmp >= O2NM_MAX_NODES)
272*0c83ed8eSKurt Hackel 		return -ERANGE;
273*0c83ed8eSKurt Hackel 
274*0c83ed8eSKurt Hackel 	/* once we're in the cl_nodes tree networking can look us up by
275*0c83ed8eSKurt Hackel 	 * node number and try to use our address and port attributes
276*0c83ed8eSKurt Hackel 	 * to connect to this node.. make sure that they've been set
277*0c83ed8eSKurt Hackel 	 * before writing the node attribute? */
278*0c83ed8eSKurt Hackel 	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
279*0c83ed8eSKurt Hackel 	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
280*0c83ed8eSKurt Hackel 		return -EINVAL; /* XXX */
281*0c83ed8eSKurt Hackel 
282*0c83ed8eSKurt Hackel 	write_lock(&cluster->cl_nodes_lock);
283*0c83ed8eSKurt Hackel 	if (cluster->cl_nodes[tmp])
284*0c83ed8eSKurt Hackel 		p = NULL;
285*0c83ed8eSKurt Hackel 	else  {
286*0c83ed8eSKurt Hackel 		cluster->cl_nodes[tmp] = node;
287*0c83ed8eSKurt Hackel 		node->nd_num = tmp;
288*0c83ed8eSKurt Hackel 		set_bit(tmp, cluster->cl_nodes_bitmap);
289*0c83ed8eSKurt Hackel 	}
290*0c83ed8eSKurt Hackel 	write_unlock(&cluster->cl_nodes_lock);
291*0c83ed8eSKurt Hackel 	if (p == NULL)
292*0c83ed8eSKurt Hackel 		return -EEXIST;
293*0c83ed8eSKurt Hackel 
294*0c83ed8eSKurt Hackel 	return count;
295*0c83ed8eSKurt Hackel }
296*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page)
297*0c83ed8eSKurt Hackel {
298*0c83ed8eSKurt Hackel 	return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port));
299*0c83ed8eSKurt Hackel }
300*0c83ed8eSKurt Hackel 
301*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node,
302*0c83ed8eSKurt Hackel 					 const char *page, size_t count)
303*0c83ed8eSKurt Hackel {
304*0c83ed8eSKurt Hackel 	unsigned long tmp;
305*0c83ed8eSKurt Hackel 	char *p = (char *)page;
306*0c83ed8eSKurt Hackel 
307*0c83ed8eSKurt Hackel 	tmp = simple_strtoul(p, &p, 0);
308*0c83ed8eSKurt Hackel 	if (!p || (*p && (*p != '\n')))
309*0c83ed8eSKurt Hackel 		return -EINVAL;
310*0c83ed8eSKurt Hackel 
311*0c83ed8eSKurt Hackel 	if (tmp == 0)
312*0c83ed8eSKurt Hackel 		return -EINVAL;
313*0c83ed8eSKurt Hackel 	if (tmp >= (u16)-1)
314*0c83ed8eSKurt Hackel 		return -ERANGE;
315*0c83ed8eSKurt Hackel 
316*0c83ed8eSKurt Hackel 	node->nd_ipv4_port = htons(tmp);
317*0c83ed8eSKurt Hackel 
318*0c83ed8eSKurt Hackel 	return count;
319*0c83ed8eSKurt Hackel }
320*0c83ed8eSKurt Hackel 
321*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page)
322*0c83ed8eSKurt Hackel {
323*0c83ed8eSKurt Hackel 	return sprintf(page, "%u.%u.%u.%u\n", NIPQUAD(node->nd_ipv4_address));
324*0c83ed8eSKurt Hackel }
325*0c83ed8eSKurt Hackel 
326*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
327*0c83ed8eSKurt Hackel 					    const char *page,
328*0c83ed8eSKurt Hackel 					    size_t count)
329*0c83ed8eSKurt Hackel {
330*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
331*0c83ed8eSKurt Hackel 	int ret, i;
332*0c83ed8eSKurt Hackel 	struct rb_node **p, *parent;
333*0c83ed8eSKurt Hackel 	unsigned int octets[4];
334*0c83ed8eSKurt Hackel 	__be32 ipv4_addr = 0;
335*0c83ed8eSKurt Hackel 
336*0c83ed8eSKurt Hackel 	ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2],
337*0c83ed8eSKurt Hackel 		     &octets[1], &octets[0]);
338*0c83ed8eSKurt Hackel 	if (ret != 4)
339*0c83ed8eSKurt Hackel 		return -EINVAL;
340*0c83ed8eSKurt Hackel 
341*0c83ed8eSKurt Hackel 	for (i = 0; i < ARRAY_SIZE(octets); i++) {
342*0c83ed8eSKurt Hackel 		if (octets[i] > 255)
343*0c83ed8eSKurt Hackel 			return -ERANGE;
344*0c83ed8eSKurt Hackel 		be32_add_cpu(&ipv4_addr, octets[i] << (i * 8));
345*0c83ed8eSKurt Hackel 	}
346*0c83ed8eSKurt Hackel 
347*0c83ed8eSKurt Hackel 	ret = 0;
348*0c83ed8eSKurt Hackel 	write_lock(&cluster->cl_nodes_lock);
349*0c83ed8eSKurt Hackel 	if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
350*0c83ed8eSKurt Hackel 		ret = -EEXIST;
351*0c83ed8eSKurt Hackel 	else {
352*0c83ed8eSKurt Hackel 		rb_link_node(&node->nd_ip_node, parent, p);
353*0c83ed8eSKurt Hackel 		rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
354*0c83ed8eSKurt Hackel 	}
355*0c83ed8eSKurt Hackel 	write_unlock(&cluster->cl_nodes_lock);
356*0c83ed8eSKurt Hackel 	if (ret)
357*0c83ed8eSKurt Hackel 		return ret;
358*0c83ed8eSKurt Hackel 
359*0c83ed8eSKurt Hackel 	memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr));
360*0c83ed8eSKurt Hackel 
361*0c83ed8eSKurt Hackel 	return count;
362*0c83ed8eSKurt Hackel }
363*0c83ed8eSKurt Hackel 
364*0c83ed8eSKurt Hackel static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page)
365*0c83ed8eSKurt Hackel {
366*0c83ed8eSKurt Hackel 	return sprintf(page, "%d\n", node->nd_local);
367*0c83ed8eSKurt Hackel }
368*0c83ed8eSKurt Hackel 
369*0c83ed8eSKurt Hackel static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page,
370*0c83ed8eSKurt Hackel 				     size_t count)
371*0c83ed8eSKurt Hackel {
372*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
373*0c83ed8eSKurt Hackel 	unsigned long tmp;
374*0c83ed8eSKurt Hackel 	char *p = (char *)page;
375*0c83ed8eSKurt Hackel 	ssize_t ret;
376*0c83ed8eSKurt Hackel 
377*0c83ed8eSKurt Hackel 	tmp = simple_strtoul(p, &p, 0);
378*0c83ed8eSKurt Hackel 	if (!p || (*p && (*p != '\n')))
379*0c83ed8eSKurt Hackel 		return -EINVAL;
380*0c83ed8eSKurt Hackel 
381*0c83ed8eSKurt Hackel 	tmp = !!tmp; /* boolean of whether this node wants to be local */
382*0c83ed8eSKurt Hackel 
383*0c83ed8eSKurt Hackel 	/* setting local turns on networking rx for now so we require having
384*0c83ed8eSKurt Hackel 	 * set everything else first */
385*0c83ed8eSKurt Hackel 	if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
386*0c83ed8eSKurt Hackel 	    !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) ||
387*0c83ed8eSKurt Hackel 	    !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
388*0c83ed8eSKurt Hackel 		return -EINVAL; /* XXX */
389*0c83ed8eSKurt Hackel 
390*0c83ed8eSKurt Hackel 	/* the only failure case is trying to set a new local node
391*0c83ed8eSKurt Hackel 	 * when a different one is already set */
392*0c83ed8eSKurt Hackel 	if (tmp && tmp == cluster->cl_has_local &&
393*0c83ed8eSKurt Hackel 	    cluster->cl_local_node != node->nd_num)
394*0c83ed8eSKurt Hackel 		return -EBUSY;
395*0c83ed8eSKurt Hackel 
396*0c83ed8eSKurt Hackel 	/* bring up the rx thread if we're setting the new local node. */
397*0c83ed8eSKurt Hackel 	if (tmp && !cluster->cl_has_local) {
398*0c83ed8eSKurt Hackel 		ret = o2net_start_listening(node);
399*0c83ed8eSKurt Hackel 		if (ret)
400*0c83ed8eSKurt Hackel 			return ret;
401*0c83ed8eSKurt Hackel 	}
402*0c83ed8eSKurt Hackel 
403*0c83ed8eSKurt Hackel 	if (!tmp && cluster->cl_has_local &&
404*0c83ed8eSKurt Hackel 	    cluster->cl_local_node == node->nd_num) {
405*0c83ed8eSKurt Hackel 		o2net_stop_listening(node);
406*0c83ed8eSKurt Hackel 		cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
407*0c83ed8eSKurt Hackel 	}
408*0c83ed8eSKurt Hackel 
409*0c83ed8eSKurt Hackel 	node->nd_local = tmp;
410*0c83ed8eSKurt Hackel 	if (node->nd_local) {
411*0c83ed8eSKurt Hackel 		cluster->cl_has_local = tmp;
412*0c83ed8eSKurt Hackel 		cluster->cl_local_node = node->nd_num;
413*0c83ed8eSKurt Hackel 	}
414*0c83ed8eSKurt Hackel 
415*0c83ed8eSKurt Hackel 	return count;
416*0c83ed8eSKurt Hackel }
417*0c83ed8eSKurt Hackel 
418*0c83ed8eSKurt Hackel struct o2nm_node_attribute {
419*0c83ed8eSKurt Hackel 	struct configfs_attribute attr;
420*0c83ed8eSKurt Hackel 	ssize_t (*show)(struct o2nm_node *, char *);
421*0c83ed8eSKurt Hackel 	ssize_t (*store)(struct o2nm_node *, const char *, size_t);
422*0c83ed8eSKurt Hackel };
423*0c83ed8eSKurt Hackel 
424*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_num = {
425*0c83ed8eSKurt Hackel 	.attr	= { .ca_owner = THIS_MODULE,
426*0c83ed8eSKurt Hackel 		    .ca_name = "num",
427*0c83ed8eSKurt Hackel 		    .ca_mode = S_IRUGO | S_IWUSR },
428*0c83ed8eSKurt Hackel 	.show	= o2nm_node_num_read,
429*0c83ed8eSKurt Hackel 	.store	= o2nm_node_num_write,
430*0c83ed8eSKurt Hackel };
431*0c83ed8eSKurt Hackel 
432*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_ipv4_port = {
433*0c83ed8eSKurt Hackel 	.attr	= { .ca_owner = THIS_MODULE,
434*0c83ed8eSKurt Hackel 		    .ca_name = "ipv4_port",
435*0c83ed8eSKurt Hackel 		    .ca_mode = S_IRUGO | S_IWUSR },
436*0c83ed8eSKurt Hackel 	.show	= o2nm_node_ipv4_port_read,
437*0c83ed8eSKurt Hackel 	.store	= o2nm_node_ipv4_port_write,
438*0c83ed8eSKurt Hackel };
439*0c83ed8eSKurt Hackel 
440*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_ipv4_address = {
441*0c83ed8eSKurt Hackel 	.attr	= { .ca_owner = THIS_MODULE,
442*0c83ed8eSKurt Hackel 		    .ca_name = "ipv4_address",
443*0c83ed8eSKurt Hackel 		    .ca_mode = S_IRUGO | S_IWUSR },
444*0c83ed8eSKurt Hackel 	.show	= o2nm_node_ipv4_address_read,
445*0c83ed8eSKurt Hackel 	.store	= o2nm_node_ipv4_address_write,
446*0c83ed8eSKurt Hackel };
447*0c83ed8eSKurt Hackel 
448*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_local = {
449*0c83ed8eSKurt Hackel 	.attr	= { .ca_owner = THIS_MODULE,
450*0c83ed8eSKurt Hackel 		    .ca_name = "local",
451*0c83ed8eSKurt Hackel 		    .ca_mode = S_IRUGO | S_IWUSR },
452*0c83ed8eSKurt Hackel 	.show	= o2nm_node_local_read,
453*0c83ed8eSKurt Hackel 	.store	= o2nm_node_local_write,
454*0c83ed8eSKurt Hackel };
455*0c83ed8eSKurt Hackel 
456*0c83ed8eSKurt Hackel static struct configfs_attribute *o2nm_node_attrs[] = {
457*0c83ed8eSKurt Hackel 	[O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr,
458*0c83ed8eSKurt Hackel 	[O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr,
459*0c83ed8eSKurt Hackel 	[O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr,
460*0c83ed8eSKurt Hackel 	[O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr,
461*0c83ed8eSKurt Hackel 	NULL,
462*0c83ed8eSKurt Hackel };
463*0c83ed8eSKurt Hackel 
464*0c83ed8eSKurt Hackel static int o2nm_attr_index(struct configfs_attribute *attr)
465*0c83ed8eSKurt Hackel {
466*0c83ed8eSKurt Hackel 	int i;
467*0c83ed8eSKurt Hackel 	for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) {
468*0c83ed8eSKurt Hackel 		if (attr == o2nm_node_attrs[i])
469*0c83ed8eSKurt Hackel 			return i;
470*0c83ed8eSKurt Hackel 	}
471*0c83ed8eSKurt Hackel 	BUG();
472*0c83ed8eSKurt Hackel 	return 0;
473*0c83ed8eSKurt Hackel }
474*0c83ed8eSKurt Hackel 
475*0c83ed8eSKurt Hackel static ssize_t o2nm_node_show(struct config_item *item,
476*0c83ed8eSKurt Hackel 			      struct configfs_attribute *attr,
477*0c83ed8eSKurt Hackel 			      char *page)
478*0c83ed8eSKurt Hackel {
479*0c83ed8eSKurt Hackel 	struct o2nm_node *node = to_o2nm_node(item);
480*0c83ed8eSKurt Hackel 	struct o2nm_node_attribute *o2nm_node_attr =
481*0c83ed8eSKurt Hackel 		container_of(attr, struct o2nm_node_attribute, attr);
482*0c83ed8eSKurt Hackel 	ssize_t ret = 0;
483*0c83ed8eSKurt Hackel 
484*0c83ed8eSKurt Hackel 	if (o2nm_node_attr->show)
485*0c83ed8eSKurt Hackel 		ret = o2nm_node_attr->show(node, page);
486*0c83ed8eSKurt Hackel 	return ret;
487*0c83ed8eSKurt Hackel }
488*0c83ed8eSKurt Hackel 
489*0c83ed8eSKurt Hackel static ssize_t o2nm_node_store(struct config_item *item,
490*0c83ed8eSKurt Hackel 			       struct configfs_attribute *attr,
491*0c83ed8eSKurt Hackel 			       const char *page, size_t count)
492*0c83ed8eSKurt Hackel {
493*0c83ed8eSKurt Hackel 	struct o2nm_node *node = to_o2nm_node(item);
494*0c83ed8eSKurt Hackel 	struct o2nm_node_attribute *o2nm_node_attr =
495*0c83ed8eSKurt Hackel 		container_of(attr, struct o2nm_node_attribute, attr);
496*0c83ed8eSKurt Hackel 	ssize_t ret;
497*0c83ed8eSKurt Hackel 	int attr_index = o2nm_attr_index(attr);
498*0c83ed8eSKurt Hackel 
499*0c83ed8eSKurt Hackel 	if (o2nm_node_attr->store == NULL) {
500*0c83ed8eSKurt Hackel 		ret = -EINVAL;
501*0c83ed8eSKurt Hackel 		goto out;
502*0c83ed8eSKurt Hackel 	}
503*0c83ed8eSKurt Hackel 
504*0c83ed8eSKurt Hackel 	if (test_bit(attr_index, &node->nd_set_attributes))
505*0c83ed8eSKurt Hackel 		return -EBUSY;
506*0c83ed8eSKurt Hackel 
507*0c83ed8eSKurt Hackel 	ret = o2nm_node_attr->store(node, page, count);
508*0c83ed8eSKurt Hackel 	if (ret < count)
509*0c83ed8eSKurt Hackel 		goto out;
510*0c83ed8eSKurt Hackel 
511*0c83ed8eSKurt Hackel 	set_bit(attr_index, &node->nd_set_attributes);
512*0c83ed8eSKurt Hackel out:
513*0c83ed8eSKurt Hackel 	return ret;
514*0c83ed8eSKurt Hackel }
515*0c83ed8eSKurt Hackel 
516*0c83ed8eSKurt Hackel static struct configfs_item_operations o2nm_node_item_ops = {
517*0c83ed8eSKurt Hackel 	.release		= o2nm_node_release,
518*0c83ed8eSKurt Hackel 	.show_attribute		= o2nm_node_show,
519*0c83ed8eSKurt Hackel 	.store_attribute	= o2nm_node_store,
520*0c83ed8eSKurt Hackel };
521*0c83ed8eSKurt Hackel 
522*0c83ed8eSKurt Hackel static struct config_item_type o2nm_node_type = {
523*0c83ed8eSKurt Hackel 	.ct_item_ops	= &o2nm_node_item_ops,
524*0c83ed8eSKurt Hackel 	.ct_attrs	= o2nm_node_attrs,
525*0c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
526*0c83ed8eSKurt Hackel };
527*0c83ed8eSKurt Hackel 
528*0c83ed8eSKurt Hackel /* node set */
529*0c83ed8eSKurt Hackel 
530*0c83ed8eSKurt Hackel struct o2nm_node_group {
531*0c83ed8eSKurt Hackel 	struct config_group ns_group;
532*0c83ed8eSKurt Hackel 	/* some stuff? */
533*0c83ed8eSKurt Hackel };
534*0c83ed8eSKurt Hackel 
535*0c83ed8eSKurt Hackel #if 0
536*0c83ed8eSKurt Hackel static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
537*0c83ed8eSKurt Hackel {
538*0c83ed8eSKurt Hackel 	return group ?
539*0c83ed8eSKurt Hackel 		container_of(group, struct o2nm_node_group, ns_group)
540*0c83ed8eSKurt Hackel 		: NULL;
541*0c83ed8eSKurt Hackel }
542*0c83ed8eSKurt Hackel #endif
543*0c83ed8eSKurt Hackel 
544*0c83ed8eSKurt Hackel static struct config_item *o2nm_node_group_make_item(struct config_group *group,
545*0c83ed8eSKurt Hackel 						     const char *name)
546*0c83ed8eSKurt Hackel {
547*0c83ed8eSKurt Hackel 	struct o2nm_node *node = NULL;
548*0c83ed8eSKurt Hackel 	struct config_item *ret = NULL;
549*0c83ed8eSKurt Hackel 
550*0c83ed8eSKurt Hackel 	if (strlen(name) > O2NM_MAX_NAME_LEN)
551*0c83ed8eSKurt Hackel 		goto out; /* ENAMETOOLONG */
552*0c83ed8eSKurt Hackel 
553*0c83ed8eSKurt Hackel 	node = kcalloc(1, sizeof(struct o2nm_node), GFP_KERNEL);
554*0c83ed8eSKurt Hackel 	if (node == NULL)
555*0c83ed8eSKurt Hackel 		goto out; /* ENOMEM */
556*0c83ed8eSKurt Hackel 
557*0c83ed8eSKurt Hackel 	strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
558*0c83ed8eSKurt Hackel 	config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
559*0c83ed8eSKurt Hackel 	spin_lock_init(&node->nd_lock);
560*0c83ed8eSKurt Hackel 
561*0c83ed8eSKurt Hackel 	ret = &node->nd_item;
562*0c83ed8eSKurt Hackel 
563*0c83ed8eSKurt Hackel out:
564*0c83ed8eSKurt Hackel 	if (ret == NULL)
565*0c83ed8eSKurt Hackel 		kfree(node);
566*0c83ed8eSKurt Hackel 
567*0c83ed8eSKurt Hackel 	return ret;
568*0c83ed8eSKurt Hackel }
569*0c83ed8eSKurt Hackel 
570*0c83ed8eSKurt Hackel static void o2nm_node_group_drop_item(struct config_group *group,
571*0c83ed8eSKurt Hackel 				      struct config_item *item)
572*0c83ed8eSKurt Hackel {
573*0c83ed8eSKurt Hackel 	struct o2nm_node *node = to_o2nm_node(item);
574*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent);
575*0c83ed8eSKurt Hackel 
576*0c83ed8eSKurt Hackel 	o2net_disconnect_node(node);
577*0c83ed8eSKurt Hackel 
578*0c83ed8eSKurt Hackel 	if (cluster->cl_has_local &&
579*0c83ed8eSKurt Hackel 	    (cluster->cl_local_node == node->nd_num)) {
580*0c83ed8eSKurt Hackel 		cluster->cl_has_local = 0;
581*0c83ed8eSKurt Hackel 		cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
582*0c83ed8eSKurt Hackel 		o2net_stop_listening(node);
583*0c83ed8eSKurt Hackel 	}
584*0c83ed8eSKurt Hackel 
585*0c83ed8eSKurt Hackel 	/* XXX call into net to stop this node from trading messages */
586*0c83ed8eSKurt Hackel 
587*0c83ed8eSKurt Hackel 	write_lock(&cluster->cl_nodes_lock);
588*0c83ed8eSKurt Hackel 
589*0c83ed8eSKurt Hackel 	/* XXX sloppy */
590*0c83ed8eSKurt Hackel 	if (node->nd_ipv4_address)
591*0c83ed8eSKurt Hackel 		rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree);
592*0c83ed8eSKurt Hackel 
593*0c83ed8eSKurt Hackel 	/* nd_num might be 0 if the node number hasn't been set.. */
594*0c83ed8eSKurt Hackel 	if (cluster->cl_nodes[node->nd_num] == node) {
595*0c83ed8eSKurt Hackel 		cluster->cl_nodes[node->nd_num] = NULL;
596*0c83ed8eSKurt Hackel 		clear_bit(node->nd_num, cluster->cl_nodes_bitmap);
597*0c83ed8eSKurt Hackel 	}
598*0c83ed8eSKurt Hackel 	write_unlock(&cluster->cl_nodes_lock);
599*0c83ed8eSKurt Hackel 
600*0c83ed8eSKurt Hackel 	config_item_put(item);
601*0c83ed8eSKurt Hackel }
602*0c83ed8eSKurt Hackel 
603*0c83ed8eSKurt Hackel static struct configfs_group_operations o2nm_node_group_group_ops = {
604*0c83ed8eSKurt Hackel 	.make_item	= o2nm_node_group_make_item,
605*0c83ed8eSKurt Hackel 	.drop_item	= o2nm_node_group_drop_item,
606*0c83ed8eSKurt Hackel };
607*0c83ed8eSKurt Hackel 
608*0c83ed8eSKurt Hackel static struct config_item_type o2nm_node_group_type = {
609*0c83ed8eSKurt Hackel 	.ct_group_ops	= &o2nm_node_group_group_ops,
610*0c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
611*0c83ed8eSKurt Hackel };
612*0c83ed8eSKurt Hackel 
613*0c83ed8eSKurt Hackel /* cluster */
614*0c83ed8eSKurt Hackel 
615*0c83ed8eSKurt Hackel static void o2nm_cluster_release(struct config_item *item)
616*0c83ed8eSKurt Hackel {
617*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
618*0c83ed8eSKurt Hackel 
619*0c83ed8eSKurt Hackel 	kfree(cluster->cl_group.default_groups);
620*0c83ed8eSKurt Hackel 	kfree(cluster);
621*0c83ed8eSKurt Hackel }
622*0c83ed8eSKurt Hackel 
623*0c83ed8eSKurt Hackel static struct configfs_item_operations o2nm_cluster_item_ops = {
624*0c83ed8eSKurt Hackel 	.release	= o2nm_cluster_release,
625*0c83ed8eSKurt Hackel };
626*0c83ed8eSKurt Hackel 
627*0c83ed8eSKurt Hackel static struct config_item_type o2nm_cluster_type = {
628*0c83ed8eSKurt Hackel 	.ct_item_ops	= &o2nm_cluster_item_ops,
629*0c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
630*0c83ed8eSKurt Hackel };
631*0c83ed8eSKurt Hackel 
632*0c83ed8eSKurt Hackel /* cluster set */
633*0c83ed8eSKurt Hackel 
634*0c83ed8eSKurt Hackel struct o2nm_cluster_group {
635*0c83ed8eSKurt Hackel 	struct configfs_subsystem cs_subsys;
636*0c83ed8eSKurt Hackel 	/* some stuff? */
637*0c83ed8eSKurt Hackel };
638*0c83ed8eSKurt Hackel 
639*0c83ed8eSKurt Hackel #if 0
640*0c83ed8eSKurt Hackel static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group)
641*0c83ed8eSKurt Hackel {
642*0c83ed8eSKurt Hackel 	return group ?
643*0c83ed8eSKurt Hackel 		container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys)
644*0c83ed8eSKurt Hackel 	       : NULL;
645*0c83ed8eSKurt Hackel }
646*0c83ed8eSKurt Hackel #endif
647*0c83ed8eSKurt Hackel 
648*0c83ed8eSKurt Hackel static struct config_group *o2nm_cluster_group_make_group(struct config_group *group,
649*0c83ed8eSKurt Hackel 							  const char *name)
650*0c83ed8eSKurt Hackel {
651*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = NULL;
652*0c83ed8eSKurt Hackel 	struct o2nm_node_group *ns = NULL;
653*0c83ed8eSKurt Hackel 	struct config_group *o2hb_group = NULL, *ret = NULL;
654*0c83ed8eSKurt Hackel 	void *defs = NULL;
655*0c83ed8eSKurt Hackel 
656*0c83ed8eSKurt Hackel 	/* this runs under the parent dir's i_sem; there can be only
657*0c83ed8eSKurt Hackel 	 * one caller in here at a time */
658*0c83ed8eSKurt Hackel 	if (o2nm_single_cluster)
659*0c83ed8eSKurt Hackel 		goto out; /* ENOSPC */
660*0c83ed8eSKurt Hackel 
661*0c83ed8eSKurt Hackel 	cluster = kcalloc(1, sizeof(struct o2nm_cluster), GFP_KERNEL);
662*0c83ed8eSKurt Hackel 	ns = kcalloc(1, sizeof(struct o2nm_node_group), GFP_KERNEL);
663*0c83ed8eSKurt Hackel 	defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
664*0c83ed8eSKurt Hackel 	o2hb_group = o2hb_alloc_hb_set();
665*0c83ed8eSKurt Hackel 	if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL)
666*0c83ed8eSKurt Hackel 		goto out;
667*0c83ed8eSKurt Hackel 
668*0c83ed8eSKurt Hackel 	config_group_init_type_name(&cluster->cl_group, name,
669*0c83ed8eSKurt Hackel 				    &o2nm_cluster_type);
670*0c83ed8eSKurt Hackel 	config_group_init_type_name(&ns->ns_group, "node",
671*0c83ed8eSKurt Hackel 				    &o2nm_node_group_type);
672*0c83ed8eSKurt Hackel 
673*0c83ed8eSKurt Hackel 	cluster->cl_group.default_groups = defs;
674*0c83ed8eSKurt Hackel 	cluster->cl_group.default_groups[0] = &ns->ns_group;
675*0c83ed8eSKurt Hackel 	cluster->cl_group.default_groups[1] = o2hb_group;
676*0c83ed8eSKurt Hackel 	cluster->cl_group.default_groups[2] = NULL;
677*0c83ed8eSKurt Hackel 	rwlock_init(&cluster->cl_nodes_lock);
678*0c83ed8eSKurt Hackel 	cluster->cl_node_ip_tree = RB_ROOT;
679*0c83ed8eSKurt Hackel 
680*0c83ed8eSKurt Hackel 	ret = &cluster->cl_group;
681*0c83ed8eSKurt Hackel 	o2nm_single_cluster = cluster;
682*0c83ed8eSKurt Hackel 
683*0c83ed8eSKurt Hackel out:
684*0c83ed8eSKurt Hackel 	if (ret == NULL) {
685*0c83ed8eSKurt Hackel 		kfree(cluster);
686*0c83ed8eSKurt Hackel 		kfree(ns);
687*0c83ed8eSKurt Hackel 		o2hb_free_hb_set(o2hb_group);
688*0c83ed8eSKurt Hackel 		kfree(defs);
689*0c83ed8eSKurt Hackel 	}
690*0c83ed8eSKurt Hackel 
691*0c83ed8eSKurt Hackel 	return ret;
692*0c83ed8eSKurt Hackel }
693*0c83ed8eSKurt Hackel 
694*0c83ed8eSKurt Hackel static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item)
695*0c83ed8eSKurt Hackel {
696*0c83ed8eSKurt Hackel 	struct o2nm_cluster *cluster = to_o2nm_cluster(item);
697*0c83ed8eSKurt Hackel 	int i;
698*0c83ed8eSKurt Hackel 	struct config_item *killme;
699*0c83ed8eSKurt Hackel 
700*0c83ed8eSKurt Hackel 	BUG_ON(o2nm_single_cluster != cluster);
701*0c83ed8eSKurt Hackel 	o2nm_single_cluster = NULL;
702*0c83ed8eSKurt Hackel 
703*0c83ed8eSKurt Hackel 	for (i = 0; cluster->cl_group.default_groups[i]; i++) {
704*0c83ed8eSKurt Hackel 		killme = &cluster->cl_group.default_groups[i]->cg_item;
705*0c83ed8eSKurt Hackel 		cluster->cl_group.default_groups[i] = NULL;
706*0c83ed8eSKurt Hackel 		config_item_put(killme);
707*0c83ed8eSKurt Hackel 	}
708*0c83ed8eSKurt Hackel 
709*0c83ed8eSKurt Hackel 	config_item_put(item);
710*0c83ed8eSKurt Hackel }
711*0c83ed8eSKurt Hackel 
712*0c83ed8eSKurt Hackel static struct configfs_group_operations o2nm_cluster_group_group_ops = {
713*0c83ed8eSKurt Hackel 	.make_group	= o2nm_cluster_group_make_group,
714*0c83ed8eSKurt Hackel 	.drop_item	= o2nm_cluster_group_drop_item,
715*0c83ed8eSKurt Hackel };
716*0c83ed8eSKurt Hackel 
717*0c83ed8eSKurt Hackel static struct config_item_type o2nm_cluster_group_type = {
718*0c83ed8eSKurt Hackel 	.ct_group_ops	= &o2nm_cluster_group_group_ops,
719*0c83ed8eSKurt Hackel 	.ct_owner	= THIS_MODULE,
720*0c83ed8eSKurt Hackel };
721*0c83ed8eSKurt Hackel 
722*0c83ed8eSKurt Hackel static struct o2nm_cluster_group o2nm_cluster_group = {
723*0c83ed8eSKurt Hackel 	.cs_subsys = {
724*0c83ed8eSKurt Hackel 		.su_group = {
725*0c83ed8eSKurt Hackel 			.cg_item = {
726*0c83ed8eSKurt Hackel 				.ci_namebuf = "cluster",
727*0c83ed8eSKurt Hackel 				.ci_type = &o2nm_cluster_group_type,
728*0c83ed8eSKurt Hackel 			},
729*0c83ed8eSKurt Hackel 		},
730*0c83ed8eSKurt Hackel 	},
731*0c83ed8eSKurt Hackel };
732*0c83ed8eSKurt Hackel 
733*0c83ed8eSKurt Hackel static void __exit exit_o2nm(void)
734*0c83ed8eSKurt Hackel {
735*0c83ed8eSKurt Hackel 	if (ocfs2_table_header)
736*0c83ed8eSKurt Hackel 		unregister_sysctl_table(ocfs2_table_header);
737*0c83ed8eSKurt Hackel 
738*0c83ed8eSKurt Hackel 	/* XXX sync with hb callbacks and shut down hb? */
739*0c83ed8eSKurt Hackel 	o2net_unregister_hb_callbacks();
740*0c83ed8eSKurt Hackel 	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
741*0c83ed8eSKurt Hackel 	o2cb_sys_shutdown();
742*0c83ed8eSKurt Hackel 
743*0c83ed8eSKurt Hackel 	o2net_exit();
744*0c83ed8eSKurt Hackel }
745*0c83ed8eSKurt Hackel 
746*0c83ed8eSKurt Hackel static int __init init_o2nm(void)
747*0c83ed8eSKurt Hackel {
748*0c83ed8eSKurt Hackel 	int ret = -1;
749*0c83ed8eSKurt Hackel 
750*0c83ed8eSKurt Hackel 	cluster_print_version();
751*0c83ed8eSKurt Hackel 
752*0c83ed8eSKurt Hackel 	o2hb_init();
753*0c83ed8eSKurt Hackel 	o2net_init();
754*0c83ed8eSKurt Hackel 
755*0c83ed8eSKurt Hackel 	ocfs2_table_header = register_sysctl_table(ocfs2_root_table, 0);
756*0c83ed8eSKurt Hackel 	if (!ocfs2_table_header) {
757*0c83ed8eSKurt Hackel 		printk(KERN_ERR "nodemanager: unable to register sysctl\n");
758*0c83ed8eSKurt Hackel 		ret = -ENOMEM; /* or something. */
759*0c83ed8eSKurt Hackel 		goto out;
760*0c83ed8eSKurt Hackel 	}
761*0c83ed8eSKurt Hackel 
762*0c83ed8eSKurt Hackel 	ret = o2net_register_hb_callbacks();
763*0c83ed8eSKurt Hackel 	if (ret)
764*0c83ed8eSKurt Hackel 		goto out_sysctl;
765*0c83ed8eSKurt Hackel 
766*0c83ed8eSKurt Hackel 	config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
767*0c83ed8eSKurt Hackel 	init_MUTEX(&o2nm_cluster_group.cs_subsys.su_sem);
768*0c83ed8eSKurt Hackel 	ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
769*0c83ed8eSKurt Hackel 	if (ret) {
770*0c83ed8eSKurt Hackel 		printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
771*0c83ed8eSKurt Hackel 		goto out_callbacks;
772*0c83ed8eSKurt Hackel 	}
773*0c83ed8eSKurt Hackel 
774*0c83ed8eSKurt Hackel 	ret = o2cb_sys_init();
775*0c83ed8eSKurt Hackel 	if (!ret)
776*0c83ed8eSKurt Hackel 		goto out;
777*0c83ed8eSKurt Hackel 
778*0c83ed8eSKurt Hackel 	configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
779*0c83ed8eSKurt Hackel out_callbacks:
780*0c83ed8eSKurt Hackel 	o2net_unregister_hb_callbacks();
781*0c83ed8eSKurt Hackel out_sysctl:
782*0c83ed8eSKurt Hackel 	unregister_sysctl_table(ocfs2_table_header);
783*0c83ed8eSKurt Hackel out:
784*0c83ed8eSKurt Hackel 	return ret;
785*0c83ed8eSKurt Hackel }
786*0c83ed8eSKurt Hackel 
787*0c83ed8eSKurt Hackel MODULE_AUTHOR("Oracle");
788*0c83ed8eSKurt Hackel MODULE_LICENSE("GPL");
789*0c83ed8eSKurt Hackel 
790*0c83ed8eSKurt Hackel module_init(init_o2nm)
791*0c83ed8eSKurt Hackel module_exit(exit_o2nm)
792