1/******************************************************************************
2*******************************************************************************
3**
4**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
5**  Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
6**
7**  This copyrighted material is made available to anyone wishing to use,
8**  modify, copy, or redistribute it subject to the terms and conditions
9**  of the GNU General Public License v.2.
10**
11*******************************************************************************
12******************************************************************************/
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/configfs.h>
17#include <linux/slab.h>
18#include <linux/in.h>
19#include <linux/in6.h>
20#include <linux/dlmconstants.h>
21#include <net/ipv6.h>
22#include <net/sock.h>
23
24#include "config.h"
25#include "lowcomms.h"
26
27/*
28 * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid
29 * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
30 * /config/dlm/<cluster>/comms/<comm>/nodeid
31 * /config/dlm/<cluster>/comms/<comm>/local
32 * /config/dlm/<cluster>/comms/<comm>/addr      (write only)
33 * /config/dlm/<cluster>/comms/<comm>/addr_list (read only)
34 * The <cluster> level is useless, but I haven't figured out how to avoid it.
35 */
36
37static struct config_group *space_list;
38static struct config_group *comm_list;
39static struct dlm_comm *local_comm;
40static uint32_t dlm_comm_count;
41
42struct dlm_clusters;
43struct dlm_cluster;
44struct dlm_spaces;
45struct dlm_space;
46struct dlm_comms;
47struct dlm_comm;
48struct dlm_nodes;
49struct dlm_node;
50
51static struct config_group *make_cluster(struct config_group *, const char *);
52static void drop_cluster(struct config_group *, struct config_item *);
53static void release_cluster(struct config_item *);
54static struct config_group *make_space(struct config_group *, const char *);
55static void drop_space(struct config_group *, struct config_item *);
56static void release_space(struct config_item *);
57static struct config_item *make_comm(struct config_group *, const char *);
58static void drop_comm(struct config_group *, struct config_item *);
59static void release_comm(struct config_item *);
60static struct config_item *make_node(struct config_group *, const char *);
61static void drop_node(struct config_group *, struct config_item *);
62static void release_node(struct config_item *);
63
64static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
65			    char *buf);
66static ssize_t store_cluster(struct config_item *i,
67			     struct configfs_attribute *a,
68			     const char *buf, size_t len);
69static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
70			 char *buf);
71static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
72			  const char *buf, size_t len);
73static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
74			 char *buf);
75static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
76			  const char *buf, size_t len);
77
78static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf);
79static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
80				size_t len);
81static ssize_t comm_local_read(struct dlm_comm *cm, char *buf);
82static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
83				size_t len);
84static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf,
85				size_t len);
86static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf);
87static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf);
88static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
89				size_t len);
90static ssize_t node_weight_read(struct dlm_node *nd, char *buf);
91static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
92				size_t len);
93
94struct dlm_cluster {
95	struct config_group group;
96	unsigned int cl_tcp_port;
97	unsigned int cl_buffer_size;
98	unsigned int cl_rsbtbl_size;
99	unsigned int cl_recover_timer;
100	unsigned int cl_toss_secs;
101	unsigned int cl_scan_secs;
102	unsigned int cl_log_debug;
103	unsigned int cl_protocol;
104	unsigned int cl_timewarn_cs;
105	unsigned int cl_waitwarn_us;
106	unsigned int cl_new_rsb_count;
107	unsigned int cl_recover_callbacks;
108	char cl_cluster_name[DLM_LOCKSPACE_LEN];
109};
110
111enum {
112	CLUSTER_ATTR_TCP_PORT = 0,
113	CLUSTER_ATTR_BUFFER_SIZE,
114	CLUSTER_ATTR_RSBTBL_SIZE,
115	CLUSTER_ATTR_RECOVER_TIMER,
116	CLUSTER_ATTR_TOSS_SECS,
117	CLUSTER_ATTR_SCAN_SECS,
118	CLUSTER_ATTR_LOG_DEBUG,
119	CLUSTER_ATTR_PROTOCOL,
120	CLUSTER_ATTR_TIMEWARN_CS,
121	CLUSTER_ATTR_WAITWARN_US,
122	CLUSTER_ATTR_NEW_RSB_COUNT,
123	CLUSTER_ATTR_RECOVER_CALLBACKS,
124	CLUSTER_ATTR_CLUSTER_NAME,
125};
126
127struct cluster_attribute {
128	struct configfs_attribute attr;
129	ssize_t (*show)(struct dlm_cluster *, char *);
130	ssize_t (*store)(struct dlm_cluster *, const char *, size_t);
131};
132
133static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf)
134{
135	return sprintf(buf, "%s\n", cl->cl_cluster_name);
136}
137
138static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl,
139					  const char *buf, size_t len)
140{
141	strlcpy(dlm_config.ci_cluster_name, buf,
142				sizeof(dlm_config.ci_cluster_name));
143	strlcpy(cl->cl_cluster_name, buf, sizeof(cl->cl_cluster_name));
144	return len;
145}
146
147static struct cluster_attribute cluster_attr_cluster_name = {
148	.attr   = { .ca_owner = THIS_MODULE,
149                    .ca_name = "cluster_name",
150                    .ca_mode = S_IRUGO | S_IWUSR },
151	.show   = cluster_cluster_name_read,
152	.store  = cluster_cluster_name_write,
153};
154
155static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
156			   int *info_field, int check_zero,
157			   const char *buf, size_t len)
158{
159	unsigned int x;
160	int rc;
161
162	if (!capable(CAP_SYS_ADMIN))
163		return -EPERM;
164	rc = kstrtouint(buf, 0, &x);
165	if (rc)
166		return rc;
167
168	if (check_zero && !x)
169		return -EINVAL;
170
171	*cl_field = x;
172	*info_field = x;
173
174	return len;
175}
176
177#define CLUSTER_ATTR(name, check_zero)                                        \
178static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \
179{                                                                             \
180	return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
181			   check_zero, buf, len);                             \
182}                                                                             \
183static ssize_t name##_read(struct dlm_cluster *cl, char *buf)                 \
184{                                                                             \
185	return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
186}                                                                             \
187static struct cluster_attribute cluster_attr_##name =                         \
188__CONFIGFS_ATTR(name, 0644, name##_read, name##_write)
189
190CLUSTER_ATTR(tcp_port, 1);
191CLUSTER_ATTR(buffer_size, 1);
192CLUSTER_ATTR(rsbtbl_size, 1);
193CLUSTER_ATTR(recover_timer, 1);
194CLUSTER_ATTR(toss_secs, 1);
195CLUSTER_ATTR(scan_secs, 1);
196CLUSTER_ATTR(log_debug, 0);
197CLUSTER_ATTR(protocol, 0);
198CLUSTER_ATTR(timewarn_cs, 1);
199CLUSTER_ATTR(waitwarn_us, 0);
200CLUSTER_ATTR(new_rsb_count, 0);
201CLUSTER_ATTR(recover_callbacks, 0);
202
203static struct configfs_attribute *cluster_attrs[] = {
204	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
205	[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr,
206	[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr,
207	[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr,
208	[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
209	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
210	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
211	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
212	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
213	[CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
214	[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
215	[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr,
216	[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr,
217	NULL,
218};
219
220enum {
221	COMM_ATTR_NODEID = 0,
222	COMM_ATTR_LOCAL,
223	COMM_ATTR_ADDR,
224	COMM_ATTR_ADDR_LIST,
225};
226
227struct comm_attribute {
228	struct configfs_attribute attr;
229	ssize_t (*show)(struct dlm_comm *, char *);
230	ssize_t (*store)(struct dlm_comm *, const char *, size_t);
231};
232
233static struct comm_attribute comm_attr_nodeid = {
234	.attr   = { .ca_owner = THIS_MODULE,
235                    .ca_name = "nodeid",
236                    .ca_mode = S_IRUGO | S_IWUSR },
237	.show   = comm_nodeid_read,
238	.store  = comm_nodeid_write,
239};
240
241static struct comm_attribute comm_attr_local = {
242	.attr   = { .ca_owner = THIS_MODULE,
243                    .ca_name = "local",
244                    .ca_mode = S_IRUGO | S_IWUSR },
245	.show   = comm_local_read,
246	.store  = comm_local_write,
247};
248
249static struct comm_attribute comm_attr_addr = {
250	.attr   = { .ca_owner = THIS_MODULE,
251                    .ca_name = "addr",
252                    .ca_mode = S_IWUSR },
253	.store  = comm_addr_write,
254};
255
256static struct comm_attribute comm_attr_addr_list = {
257	.attr   = { .ca_owner = THIS_MODULE,
258                    .ca_name = "addr_list",
259                    .ca_mode = S_IRUGO },
260	.show   = comm_addr_list_read,
261};
262
263static struct configfs_attribute *comm_attrs[] = {
264	[COMM_ATTR_NODEID] = &comm_attr_nodeid.attr,
265	[COMM_ATTR_LOCAL] = &comm_attr_local.attr,
266	[COMM_ATTR_ADDR] = &comm_attr_addr.attr,
267	[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list.attr,
268	NULL,
269};
270
271enum {
272	NODE_ATTR_NODEID = 0,
273	NODE_ATTR_WEIGHT,
274};
275
276struct node_attribute {
277	struct configfs_attribute attr;
278	ssize_t (*show)(struct dlm_node *, char *);
279	ssize_t (*store)(struct dlm_node *, const char *, size_t);
280};
281
282static struct node_attribute node_attr_nodeid = {
283	.attr   = { .ca_owner = THIS_MODULE,
284                    .ca_name = "nodeid",
285                    .ca_mode = S_IRUGO | S_IWUSR },
286	.show   = node_nodeid_read,
287	.store  = node_nodeid_write,
288};
289
290static struct node_attribute node_attr_weight = {
291	.attr   = { .ca_owner = THIS_MODULE,
292                    .ca_name = "weight",
293                    .ca_mode = S_IRUGO | S_IWUSR },
294	.show   = node_weight_read,
295	.store  = node_weight_write,
296};
297
298static struct configfs_attribute *node_attrs[] = {
299	[NODE_ATTR_NODEID] = &node_attr_nodeid.attr,
300	[NODE_ATTR_WEIGHT] = &node_attr_weight.attr,
301	NULL,
302};
303
304struct dlm_clusters {
305	struct configfs_subsystem subsys;
306};
307
308struct dlm_spaces {
309	struct config_group ss_group;
310};
311
312struct dlm_space {
313	struct config_group group;
314	struct list_head members;
315	struct mutex members_lock;
316	int members_count;
317};
318
319struct dlm_comms {
320	struct config_group cs_group;
321};
322
323struct dlm_comm {
324	struct config_item item;
325	int seq;
326	int nodeid;
327	int local;
328	int addr_count;
329	struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
330};
331
332struct dlm_nodes {
333	struct config_group ns_group;
334};
335
336struct dlm_node {
337	struct config_item item;
338	struct list_head list; /* space->members */
339	int nodeid;
340	int weight;
341	int new;
342	int comm_seq; /* copy of cm->seq when nd->nodeid is set */
343};
344
345static struct configfs_group_operations clusters_ops = {
346	.make_group = make_cluster,
347	.drop_item = drop_cluster,
348};
349
350static struct configfs_item_operations cluster_ops = {
351	.release = release_cluster,
352	.show_attribute = show_cluster,
353	.store_attribute = store_cluster,
354};
355
356static struct configfs_group_operations spaces_ops = {
357	.make_group = make_space,
358	.drop_item = drop_space,
359};
360
361static struct configfs_item_operations space_ops = {
362	.release = release_space,
363};
364
365static struct configfs_group_operations comms_ops = {
366	.make_item = make_comm,
367	.drop_item = drop_comm,
368};
369
370static struct configfs_item_operations comm_ops = {
371	.release = release_comm,
372	.show_attribute = show_comm,
373	.store_attribute = store_comm,
374};
375
376static struct configfs_group_operations nodes_ops = {
377	.make_item = make_node,
378	.drop_item = drop_node,
379};
380
381static struct configfs_item_operations node_ops = {
382	.release = release_node,
383	.show_attribute = show_node,
384	.store_attribute = store_node,
385};
386
387static struct config_item_type clusters_type = {
388	.ct_group_ops = &clusters_ops,
389	.ct_owner = THIS_MODULE,
390};
391
392static struct config_item_type cluster_type = {
393	.ct_item_ops = &cluster_ops,
394	.ct_attrs = cluster_attrs,
395	.ct_owner = THIS_MODULE,
396};
397
398static struct config_item_type spaces_type = {
399	.ct_group_ops = &spaces_ops,
400	.ct_owner = THIS_MODULE,
401};
402
403static struct config_item_type space_type = {
404	.ct_item_ops = &space_ops,
405	.ct_owner = THIS_MODULE,
406};
407
408static struct config_item_type comms_type = {
409	.ct_group_ops = &comms_ops,
410	.ct_owner = THIS_MODULE,
411};
412
413static struct config_item_type comm_type = {
414	.ct_item_ops = &comm_ops,
415	.ct_attrs = comm_attrs,
416	.ct_owner = THIS_MODULE,
417};
418
419static struct config_item_type nodes_type = {
420	.ct_group_ops = &nodes_ops,
421	.ct_owner = THIS_MODULE,
422};
423
424static struct config_item_type node_type = {
425	.ct_item_ops = &node_ops,
426	.ct_attrs = node_attrs,
427	.ct_owner = THIS_MODULE,
428};
429
430static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
431{
432	return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
433		   NULL;
434}
435
436static struct dlm_space *config_item_to_space(struct config_item *i)
437{
438	return i ? container_of(to_config_group(i), struct dlm_space, group) :
439		   NULL;
440}
441
442static struct dlm_comm *config_item_to_comm(struct config_item *i)
443{
444	return i ? container_of(i, struct dlm_comm, item) : NULL;
445}
446
447static struct dlm_node *config_item_to_node(struct config_item *i)
448{
449	return i ? container_of(i, struct dlm_node, item) : NULL;
450}
451
452static struct config_group *make_cluster(struct config_group *g,
453					 const char *name)
454{
455	struct dlm_cluster *cl = NULL;
456	struct dlm_spaces *sps = NULL;
457	struct dlm_comms *cms = NULL;
458	void *gps = NULL;
459
460	cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
461	gps = kcalloc(3, sizeof(struct config_group *), GFP_NOFS);
462	sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
463	cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
464
465	if (!cl || !gps || !sps || !cms)
466		goto fail;
467
468	config_group_init_type_name(&cl->group, name, &cluster_type);
469	config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
470	config_group_init_type_name(&cms->cs_group, "comms", &comms_type);
471
472	cl->group.default_groups = gps;
473	cl->group.default_groups[0] = &sps->ss_group;
474	cl->group.default_groups[1] = &cms->cs_group;
475	cl->group.default_groups[2] = NULL;
476
477	cl->cl_tcp_port = dlm_config.ci_tcp_port;
478	cl->cl_buffer_size = dlm_config.ci_buffer_size;
479	cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size;
480	cl->cl_recover_timer = dlm_config.ci_recover_timer;
481	cl->cl_toss_secs = dlm_config.ci_toss_secs;
482	cl->cl_scan_secs = dlm_config.ci_scan_secs;
483	cl->cl_log_debug = dlm_config.ci_log_debug;
484	cl->cl_protocol = dlm_config.ci_protocol;
485	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
486	cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
487	cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
488	cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
489	memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
490	       DLM_LOCKSPACE_LEN);
491
492	space_list = &sps->ss_group;
493	comm_list = &cms->cs_group;
494	return &cl->group;
495
496 fail:
497	kfree(cl);
498	kfree(gps);
499	kfree(sps);
500	kfree(cms);
501	return ERR_PTR(-ENOMEM);
502}
503
504static void drop_cluster(struct config_group *g, struct config_item *i)
505{
506	struct dlm_cluster *cl = config_item_to_cluster(i);
507	struct config_item *tmp;
508	int j;
509
510	for (j = 0; cl->group.default_groups[j]; j++) {
511		tmp = &cl->group.default_groups[j]->cg_item;
512		cl->group.default_groups[j] = NULL;
513		config_item_put(tmp);
514	}
515
516	space_list = NULL;
517	comm_list = NULL;
518
519	config_item_put(i);
520}
521
522static void release_cluster(struct config_item *i)
523{
524	struct dlm_cluster *cl = config_item_to_cluster(i);
525	kfree(cl->group.default_groups);
526	kfree(cl);
527}
528
529static struct config_group *make_space(struct config_group *g, const char *name)
530{
531	struct dlm_space *sp = NULL;
532	struct dlm_nodes *nds = NULL;
533	void *gps = NULL;
534
535	sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
536	gps = kcalloc(2, sizeof(struct config_group *), GFP_NOFS);
537	nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
538
539	if (!sp || !gps || !nds)
540		goto fail;
541
542	config_group_init_type_name(&sp->group, name, &space_type);
543	config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type);
544
545	sp->group.default_groups = gps;
546	sp->group.default_groups[0] = &nds->ns_group;
547	sp->group.default_groups[1] = NULL;
548
549	INIT_LIST_HEAD(&sp->members);
550	mutex_init(&sp->members_lock);
551	sp->members_count = 0;
552	return &sp->group;
553
554 fail:
555	kfree(sp);
556	kfree(gps);
557	kfree(nds);
558	return ERR_PTR(-ENOMEM);
559}
560
561static void drop_space(struct config_group *g, struct config_item *i)
562{
563	struct dlm_space *sp = config_item_to_space(i);
564	struct config_item *tmp;
565	int j;
566
567	/* assert list_empty(&sp->members) */
568
569	for (j = 0; sp->group.default_groups[j]; j++) {
570		tmp = &sp->group.default_groups[j]->cg_item;
571		sp->group.default_groups[j] = NULL;
572		config_item_put(tmp);
573	}
574
575	config_item_put(i);
576}
577
578static void release_space(struct config_item *i)
579{
580	struct dlm_space *sp = config_item_to_space(i);
581	kfree(sp->group.default_groups);
582	kfree(sp);
583}
584
585static struct config_item *make_comm(struct config_group *g, const char *name)
586{
587	struct dlm_comm *cm;
588
589	cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
590	if (!cm)
591		return ERR_PTR(-ENOMEM);
592
593	config_item_init_type_name(&cm->item, name, &comm_type);
594
595	cm->seq = dlm_comm_count++;
596	if (!cm->seq)
597		cm->seq = dlm_comm_count++;
598
599	cm->nodeid = -1;
600	cm->local = 0;
601	cm->addr_count = 0;
602	return &cm->item;
603}
604
605static void drop_comm(struct config_group *g, struct config_item *i)
606{
607	struct dlm_comm *cm = config_item_to_comm(i);
608	if (local_comm == cm)
609		local_comm = NULL;
610	dlm_lowcomms_close(cm->nodeid);
611	while (cm->addr_count--)
612		kfree(cm->addr[cm->addr_count]);
613	config_item_put(i);
614}
615
616static void release_comm(struct config_item *i)
617{
618	struct dlm_comm *cm = config_item_to_comm(i);
619	kfree(cm);
620}
621
622static struct config_item *make_node(struct config_group *g, const char *name)
623{
624	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
625	struct dlm_node *nd;
626
627	nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
628	if (!nd)
629		return ERR_PTR(-ENOMEM);
630
631	config_item_init_type_name(&nd->item, name, &node_type);
632	nd->nodeid = -1;
633	nd->weight = 1;  /* default weight of 1 if none is set */
634	nd->new = 1;     /* set to 0 once it's been read by dlm_nodeid_list() */
635
636	mutex_lock(&sp->members_lock);
637	list_add(&nd->list, &sp->members);
638	sp->members_count++;
639	mutex_unlock(&sp->members_lock);
640
641	return &nd->item;
642}
643
644static void drop_node(struct config_group *g, struct config_item *i)
645{
646	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
647	struct dlm_node *nd = config_item_to_node(i);
648
649	mutex_lock(&sp->members_lock);
650	list_del(&nd->list);
651	sp->members_count--;
652	mutex_unlock(&sp->members_lock);
653
654	config_item_put(i);
655}
656
657static void release_node(struct config_item *i)
658{
659	struct dlm_node *nd = config_item_to_node(i);
660	kfree(nd);
661}
662
663static struct dlm_clusters clusters_root = {
664	.subsys = {
665		.su_group = {
666			.cg_item = {
667				.ci_namebuf = "dlm",
668				.ci_type = &clusters_type,
669			},
670		},
671	},
672};
673
674int __init dlm_config_init(void)
675{
676	config_group_init(&clusters_root.subsys.su_group);
677	mutex_init(&clusters_root.subsys.su_mutex);
678	return configfs_register_subsystem(&clusters_root.subsys);
679}
680
681void dlm_config_exit(void)
682{
683	configfs_unregister_subsystem(&clusters_root.subsys);
684}
685
686/*
687 * Functions for user space to read/write attributes
688 */
689
690static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
691			    char *buf)
692{
693	struct dlm_cluster *cl = config_item_to_cluster(i);
694	struct cluster_attribute *cla =
695			container_of(a, struct cluster_attribute, attr);
696	return cla->show ? cla->show(cl, buf) : 0;
697}
698
699static ssize_t store_cluster(struct config_item *i,
700			     struct configfs_attribute *a,
701			     const char *buf, size_t len)
702{
703	struct dlm_cluster *cl = config_item_to_cluster(i);
704	struct cluster_attribute *cla =
705		container_of(a, struct cluster_attribute, attr);
706	return cla->store ? cla->store(cl, buf, len) : -EINVAL;
707}
708
709static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
710			 char *buf)
711{
712	struct dlm_comm *cm = config_item_to_comm(i);
713	struct comm_attribute *cma =
714			container_of(a, struct comm_attribute, attr);
715	return cma->show ? cma->show(cm, buf) : 0;
716}
717
718static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
719			  const char *buf, size_t len)
720{
721	struct dlm_comm *cm = config_item_to_comm(i);
722	struct comm_attribute *cma =
723		container_of(a, struct comm_attribute, attr);
724	return cma->store ? cma->store(cm, buf, len) : -EINVAL;
725}
726
727static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf)
728{
729	return sprintf(buf, "%d\n", cm->nodeid);
730}
731
732static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
733				 size_t len)
734{
735	int rc = kstrtoint(buf, 0, &cm->nodeid);
736
737	if (rc)
738		return rc;
739	return len;
740}
741
742static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
743{
744	return sprintf(buf, "%d\n", cm->local);
745}
746
747static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
748				size_t len)
749{
750	int rc = kstrtoint(buf, 0, &cm->local);
751
752	if (rc)
753		return rc;
754	if (cm->local && !local_comm)
755		local_comm = cm;
756	return len;
757}
758
759static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
760{
761	struct sockaddr_storage *addr;
762	int rv;
763
764	if (len != sizeof(struct sockaddr_storage))
765		return -EINVAL;
766
767	if (cm->addr_count >= DLM_MAX_ADDR_COUNT)
768		return -ENOSPC;
769
770	addr = kzalloc(sizeof(*addr), GFP_NOFS);
771	if (!addr)
772		return -ENOMEM;
773
774	memcpy(addr, buf, len);
775
776	rv = dlm_lowcomms_addr(cm->nodeid, addr, len);
777	if (rv) {
778		kfree(addr);
779		return rv;
780	}
781
782	cm->addr[cm->addr_count++] = addr;
783	return len;
784}
785
786static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf)
787{
788	ssize_t s;
789	ssize_t allowance;
790	int i;
791	struct sockaddr_storage *addr;
792	struct sockaddr_in *addr_in;
793	struct sockaddr_in6 *addr_in6;
794
795	/* Taken from ip6_addr_string() defined in lib/vsprintf.c */
796	char buf0[sizeof("AF_INET6	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255\n")];
797
798
799	/* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */
800	allowance = 4096;
801	buf[0] = '\0';
802
803	for (i = 0; i < cm->addr_count; i++) {
804		addr = cm->addr[i];
805
806		switch(addr->ss_family) {
807		case AF_INET:
808			addr_in = (struct sockaddr_in *)addr;
809			s = sprintf(buf0, "AF_INET	%pI4\n", &addr_in->sin_addr.s_addr);
810			break;
811		case AF_INET6:
812			addr_in6 = (struct sockaddr_in6 *)addr;
813			s = sprintf(buf0, "AF_INET6	%pI6\n", &addr_in6->sin6_addr);
814			break;
815		default:
816			s = sprintf(buf0, "%s\n", "<UNKNOWN>");
817			break;
818		}
819		allowance -= s;
820		if (allowance >= 0)
821			strcat(buf, buf0);
822		else {
823			allowance += s;
824			break;
825		}
826	}
827	return 4096 - allowance;
828}
829
830static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
831			 char *buf)
832{
833	struct dlm_node *nd = config_item_to_node(i);
834	struct node_attribute *nda =
835			container_of(a, struct node_attribute, attr);
836	return nda->show ? nda->show(nd, buf) : 0;
837}
838
839static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
840			  const char *buf, size_t len)
841{
842	struct dlm_node *nd = config_item_to_node(i);
843	struct node_attribute *nda =
844		container_of(a, struct node_attribute, attr);
845	return nda->store ? nda->store(nd, buf, len) : -EINVAL;
846}
847
848static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
849{
850	return sprintf(buf, "%d\n", nd->nodeid);
851}
852
853static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
854				 size_t len)
855{
856	uint32_t seq = 0;
857	int rc = kstrtoint(buf, 0, &nd->nodeid);
858
859	if (rc)
860		return rc;
861	dlm_comm_seq(nd->nodeid, &seq);
862	nd->comm_seq = seq;
863	return len;
864}
865
866static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
867{
868	return sprintf(buf, "%d\n", nd->weight);
869}
870
871static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
872				 size_t len)
873{
874	int rc = kstrtoint(buf, 0, &nd->weight);
875
876	if (rc)
877		return rc;
878	return len;
879}
880
881/*
882 * Functions for the dlm to get the info that's been configured
883 */
884
885static struct dlm_space *get_space(char *name)
886{
887	struct config_item *i;
888
889	if (!space_list)
890		return NULL;
891
892	mutex_lock(&space_list->cg_subsys->su_mutex);
893	i = config_group_find_item(space_list, name);
894	mutex_unlock(&space_list->cg_subsys->su_mutex);
895
896	return config_item_to_space(i);
897}
898
899static void put_space(struct dlm_space *sp)
900{
901	config_item_put(&sp->group.cg_item);
902}
903
904static struct dlm_comm *get_comm(int nodeid)
905{
906	struct config_item *i;
907	struct dlm_comm *cm = NULL;
908	int found = 0;
909
910	if (!comm_list)
911		return NULL;
912
913	mutex_lock(&clusters_root.subsys.su_mutex);
914
915	list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
916		cm = config_item_to_comm(i);
917
918		if (cm->nodeid != nodeid)
919			continue;
920		found = 1;
921		config_item_get(i);
922		break;
923	}
924	mutex_unlock(&clusters_root.subsys.su_mutex);
925
926	if (!found)
927		cm = NULL;
928	return cm;
929}
930
931static void put_comm(struct dlm_comm *cm)
932{
933	config_item_put(&cm->item);
934}
935
936/* caller must free mem */
937int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
938		     int *count_out)
939{
940	struct dlm_space *sp;
941	struct dlm_node *nd;
942	struct dlm_config_node *nodes, *node;
943	int rv, count;
944
945	sp = get_space(lsname);
946	if (!sp)
947		return -EEXIST;
948
949	mutex_lock(&sp->members_lock);
950	if (!sp->members_count) {
951		rv = -EINVAL;
952		printk(KERN_ERR "dlm: zero members_count\n");
953		goto out;
954	}
955
956	count = sp->members_count;
957
958	nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
959	if (!nodes) {
960		rv = -ENOMEM;
961		goto out;
962	}
963
964	node = nodes;
965	list_for_each_entry(nd, &sp->members, list) {
966		node->nodeid = nd->nodeid;
967		node->weight = nd->weight;
968		node->new = nd->new;
969		node->comm_seq = nd->comm_seq;
970		node++;
971
972		nd->new = 0;
973	}
974
975	*count_out = count;
976	*nodes_out = nodes;
977	rv = 0;
978 out:
979	mutex_unlock(&sp->members_lock);
980	put_space(sp);
981	return rv;
982}
983
984int dlm_comm_seq(int nodeid, uint32_t *seq)
985{
986	struct dlm_comm *cm = get_comm(nodeid);
987	if (!cm)
988		return -EEXIST;
989	*seq = cm->seq;
990	put_comm(cm);
991	return 0;
992}
993
994int dlm_our_nodeid(void)
995{
996	return local_comm ? local_comm->nodeid : 0;
997}
998
999/* num 0 is first addr, num 1 is second addr */
1000int dlm_our_addr(struct sockaddr_storage *addr, int num)
1001{
1002	if (!local_comm)
1003		return -1;
1004	if (num + 1 > local_comm->addr_count)
1005		return -1;
1006	memcpy(addr, local_comm->addr[num], sizeof(*addr));
1007	return 0;
1008}
1009
1010/* Config file defaults */
1011#define DEFAULT_TCP_PORT       21064
1012#define DEFAULT_BUFFER_SIZE     4096
1013#define DEFAULT_RSBTBL_SIZE     1024
1014#define DEFAULT_RECOVER_TIMER      5
1015#define DEFAULT_TOSS_SECS         10
1016#define DEFAULT_SCAN_SECS          5
1017#define DEFAULT_LOG_DEBUG          0
1018#define DEFAULT_PROTOCOL           0
1019#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
1020#define DEFAULT_WAITWARN_US	   0
1021#define DEFAULT_NEW_RSB_COUNT    128
1022#define DEFAULT_RECOVER_CALLBACKS  0
1023#define DEFAULT_CLUSTER_NAME      ""
1024
1025struct dlm_config_info dlm_config = {
1026	.ci_tcp_port = DEFAULT_TCP_PORT,
1027	.ci_buffer_size = DEFAULT_BUFFER_SIZE,
1028	.ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
1029	.ci_recover_timer = DEFAULT_RECOVER_TIMER,
1030	.ci_toss_secs = DEFAULT_TOSS_SECS,
1031	.ci_scan_secs = DEFAULT_SCAN_SECS,
1032	.ci_log_debug = DEFAULT_LOG_DEBUG,
1033	.ci_protocol = DEFAULT_PROTOCOL,
1034	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
1035	.ci_waitwarn_us = DEFAULT_WAITWARN_US,
1036	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
1037	.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
1038	.ci_cluster_name = DEFAULT_CLUSTER_NAME
1039};
1040
1041