config.c 26.5 KB
Newer Older
1 2 3 4
/******************************************************************************
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
D
David Teigland 已提交
5
**  Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
6 7 8 9 10 11 12 13 14 15 16
**
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/configfs.h>
17
#include <linux/slab.h>
D
David Teigland 已提交
18 19
#include <linux/in.h>
#include <linux/in6.h>
D
David Teigland 已提交
20
#include <linux/dlmconstants.h>
D
David Teigland 已提交
21
#include <net/ipv6.h>
22 23 24
#include <net/sock.h>

#include "config.h"
25
#include "lowcomms.h"
26 27 28 29 30 31

/*
 * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid
 * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
 * /config/dlm/<cluster>/comms/<comm>/nodeid
 * /config/dlm/<cluster>/comms/<comm>/local
32 33
 * /config/dlm/<cluster>/comms/<comm>/addr      (write only)
 * /config/dlm/<cluster>/comms/<comm>/addr_list (read only)
34 35 36 37 38
 * The <cluster> level is useless, but I haven't figured out how to avoid it.
 */

static struct config_group *space_list;
static struct config_group *comm_list;
D
David Teigland 已提交
39
static struct dlm_comm *local_comm;
D
David Teigland 已提交
40
static uint32_t dlm_comm_count;
41

D
David Teigland 已提交
42 43 44 45 46 47 48 49
struct dlm_clusters;
struct dlm_cluster;
struct dlm_spaces;
struct dlm_space;
struct dlm_comms;
struct dlm_comm;
struct dlm_nodes;
struct dlm_node;
50

51
static struct config_group *make_cluster(struct config_group *, const char *);
52 53
static void drop_cluster(struct config_group *, struct config_item *);
static void release_cluster(struct config_item *);
54
static struct config_group *make_space(struct config_group *, const char *);
55 56
static void drop_space(struct config_group *, struct config_item *);
static void release_space(struct config_item *);
57
static struct config_item *make_comm(struct config_group *, const char *);
58 59
static void drop_comm(struct config_group *, struct config_item *);
static void release_comm(struct config_item *);
60
static struct config_item *make_node(struct config_group *, const char *);
61 62 63
static void drop_node(struct config_group *, struct config_item *);
static void release_node(struct config_item *);

64 65 66 67 68
static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
			    char *buf);
static ssize_t store_cluster(struct config_item *i,
			     struct configfs_attribute *a,
			     const char *buf, size_t len);
69 70 71 72 73 74 75 76 77
static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
			 char *buf);
static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
			  const char *buf, size_t len);
static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
			 char *buf);
static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
			  const char *buf, size_t len);

D
David Teigland 已提交
78 79 80 81 82 83 84 85
static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf);
static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
				size_t len);
static ssize_t comm_local_read(struct dlm_comm *cm, char *buf);
static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
				size_t len);
static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf,
				size_t len);
86
static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf);
D
David Teigland 已提交
87 88 89 90 91 92 93 94
static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf);
static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
				size_t len);
static ssize_t node_weight_read(struct dlm_node *nd, char *buf);
static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
				size_t len);

struct dlm_cluster {
95 96 97 98 99 100 101 102
	struct config_group group;
	unsigned int cl_tcp_port;
	unsigned int cl_buffer_size;
	unsigned int cl_rsbtbl_size;
	unsigned int cl_recover_timer;
	unsigned int cl_toss_secs;
	unsigned int cl_scan_secs;
	unsigned int cl_log_debug;
103
	unsigned int cl_protocol;
104
	unsigned int cl_timewarn_cs;
105
	unsigned int cl_waitwarn_us;
D
David Teigland 已提交
106
	unsigned int cl_new_rsb_count;
D
David Teigland 已提交
107 108
	unsigned int cl_recover_callbacks;
	char cl_cluster_name[DLM_LOCKSPACE_LEN];
109 110 111 112 113 114 115 116 117 118
};

enum {
	CLUSTER_ATTR_TCP_PORT = 0,
	CLUSTER_ATTR_BUFFER_SIZE,
	CLUSTER_ATTR_RSBTBL_SIZE,
	CLUSTER_ATTR_RECOVER_TIMER,
	CLUSTER_ATTR_TOSS_SECS,
	CLUSTER_ATTR_SCAN_SECS,
	CLUSTER_ATTR_LOG_DEBUG,
119
	CLUSTER_ATTR_PROTOCOL,
120
	CLUSTER_ATTR_TIMEWARN_CS,
121
	CLUSTER_ATTR_WAITWARN_US,
D
David Teigland 已提交
122
	CLUSTER_ATTR_NEW_RSB_COUNT,
D
David Teigland 已提交
123 124
	CLUSTER_ATTR_RECOVER_CALLBACKS,
	CLUSTER_ATTR_CLUSTER_NAME,
125 126 127 128
};

struct cluster_attribute {
	struct configfs_attribute attr;
D
David Teigland 已提交
129 130
	ssize_t (*show)(struct dlm_cluster *, char *);
	ssize_t (*store)(struct dlm_cluster *, const char *, size_t);
131 132
};

D
David Teigland 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf)
{
	return sprintf(buf, "%s\n", cl->cl_cluster_name);
}

static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl,
					  const char *buf, size_t len)
{
	strncpy(dlm_config.ci_cluster_name, buf, DLM_LOCKSPACE_LEN);
	strncpy(cl->cl_cluster_name, buf, DLM_LOCKSPACE_LEN);
	return len;
}

static struct cluster_attribute cluster_attr_cluster_name = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "cluster_name",
                    .ca_mode = S_IRUGO | S_IWUSR },
	.show   = cluster_cluster_name_read,
	.store  = cluster_cluster_name_write,
};

D
David Teigland 已提交
154
static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
155
			   int *info_field, int check_zero,
156 157 158 159 160
			   const char *buf, size_t len)
{
	unsigned int x;

	if (!capable(CAP_SYS_ADMIN))
161
		return -EPERM;
162 163 164 165 166 167 168 169 170 171 172 173 174

	x = simple_strtoul(buf, NULL, 0);

	if (check_zero && !x)
		return -EINVAL;

	*cl_field = x;
	*info_field = x;

	return len;
}

#define CLUSTER_ATTR(name, check_zero)                                        \
D
David Teigland 已提交
175
static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \
176 177 178 179
{                                                                             \
	return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
			   check_zero, buf, len);                             \
}                                                                             \
D
David Teigland 已提交
180
static ssize_t name##_read(struct dlm_cluster *cl, char *buf)                 \
181 182 183 184 185 186 187 188 189 190 191 192 193
{                                                                             \
	return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
}                                                                             \
static struct cluster_attribute cluster_attr_##name =                         \
__CONFIGFS_ATTR(name, 0644, name##_read, name##_write)

CLUSTER_ATTR(tcp_port, 1);
CLUSTER_ATTR(buffer_size, 1);
CLUSTER_ATTR(rsbtbl_size, 1);
CLUSTER_ATTR(recover_timer, 1);
CLUSTER_ATTR(toss_secs, 1);
CLUSTER_ATTR(scan_secs, 1);
CLUSTER_ATTR(log_debug, 0);
194
CLUSTER_ATTR(protocol, 0);
195
CLUSTER_ATTR(timewarn_cs, 1);
196
CLUSTER_ATTR(waitwarn_us, 0);
D
David Teigland 已提交
197
CLUSTER_ATTR(new_rsb_count, 0);
D
David Teigland 已提交
198
CLUSTER_ATTR(recover_callbacks, 0);
199 200 201 202 203 204 205 206 207

static struct configfs_attribute *cluster_attrs[] = {
	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
	[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr,
	[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr,
	[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr,
	[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
208
	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
209
	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
210
	[CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
D
David Teigland 已提交
211
	[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
D
David Teigland 已提交
212 213
	[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr,
	[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr,
214 215 216
	NULL,
};

217 218 219 220
enum {
	COMM_ATTR_NODEID = 0,
	COMM_ATTR_LOCAL,
	COMM_ATTR_ADDR,
221
	COMM_ATTR_ADDR_LIST,
222 223 224 225
};

struct comm_attribute {
	struct configfs_attribute attr;
D
David Teigland 已提交
226 227
	ssize_t (*show)(struct dlm_comm *, char *);
	ssize_t (*store)(struct dlm_comm *, const char *, size_t);
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
};

static struct comm_attribute comm_attr_nodeid = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "nodeid",
                    .ca_mode = S_IRUGO | S_IWUSR },
	.show   = comm_nodeid_read,
	.store  = comm_nodeid_write,
};

static struct comm_attribute comm_attr_local = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "local",
                    .ca_mode = S_IRUGO | S_IWUSR },
	.show   = comm_local_read,
	.store  = comm_local_write,
};

static struct comm_attribute comm_attr_addr = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "addr",
249
                    .ca_mode = S_IWUSR },
250 251 252
	.store  = comm_addr_write,
};

253 254 255 256 257 258 259
static struct comm_attribute comm_attr_addr_list = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "addr_list",
                    .ca_mode = S_IRUGO },
	.show   = comm_addr_list_read,
};

260 261 262 263
static struct configfs_attribute *comm_attrs[] = {
	[COMM_ATTR_NODEID] = &comm_attr_nodeid.attr,
	[COMM_ATTR_LOCAL] = &comm_attr_local.attr,
	[COMM_ATTR_ADDR] = &comm_attr_addr.attr,
264
	[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list.attr,
265 266 267 268 269 270 271 272 273 274
	NULL,
};

enum {
	NODE_ATTR_NODEID = 0,
	NODE_ATTR_WEIGHT,
};

struct node_attribute {
	struct configfs_attribute attr;
D
David Teigland 已提交
275 276
	ssize_t (*show)(struct dlm_node *, char *);
	ssize_t (*store)(struct dlm_node *, const char *, size_t);
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
};

static struct node_attribute node_attr_nodeid = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "nodeid",
                    .ca_mode = S_IRUGO | S_IWUSR },
	.show   = node_nodeid_read,
	.store  = node_nodeid_write,
};

static struct node_attribute node_attr_weight = {
	.attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "weight",
                    .ca_mode = S_IRUGO | S_IWUSR },
	.show   = node_weight_read,
	.store  = node_weight_write,
};

static struct configfs_attribute *node_attrs[] = {
	[NODE_ATTR_NODEID] = &node_attr_nodeid.attr,
	[NODE_ATTR_WEIGHT] = &node_attr_weight.attr,
	NULL,
};

D
David Teigland 已提交
301
struct dlm_clusters {
302 303 304
	struct configfs_subsystem subsys;
};

D
David Teigland 已提交
305
struct dlm_spaces {
306 307 308
	struct config_group ss_group;
};

D
David Teigland 已提交
309
struct dlm_space {
310 311
	struct config_group group;
	struct list_head members;
312
	struct mutex members_lock;
313 314 315
	int members_count;
};

D
David Teigland 已提交
316
struct dlm_comms {
317 318 319
	struct config_group cs_group;
};

D
David Teigland 已提交
320
struct dlm_comm {
321
	struct config_item item;
D
David Teigland 已提交
322
	int seq;
323 324 325 326 327 328
	int nodeid;
	int local;
	int addr_count;
	struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
};

D
David Teigland 已提交
329
struct dlm_nodes {
330 331 332
	struct config_group ns_group;
};

D
David Teigland 已提交
333
struct dlm_node {
334 335 336 337
	struct config_item item;
	struct list_head list; /* space->members */
	int nodeid;
	int weight;
338
	int new;
D
David Teigland 已提交
339
	int comm_seq; /* copy of cm->seq when nd->nodeid is set */
340 341 342 343 344 345 346 347 348
};

static struct configfs_group_operations clusters_ops = {
	.make_group = make_cluster,
	.drop_item = drop_cluster,
};

static struct configfs_item_operations cluster_ops = {
	.release = release_cluster,
349 350
	.show_attribute = show_cluster,
	.store_attribute = store_cluster,
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
};

static struct configfs_group_operations spaces_ops = {
	.make_group = make_space,
	.drop_item = drop_space,
};

static struct configfs_item_operations space_ops = {
	.release = release_space,
};

static struct configfs_group_operations comms_ops = {
	.make_item = make_comm,
	.drop_item = drop_comm,
};

static struct configfs_item_operations comm_ops = {
	.release = release_comm,
	.show_attribute = show_comm,
	.store_attribute = store_comm,
};

static struct configfs_group_operations nodes_ops = {
	.make_item = make_node,
	.drop_item = drop_node,
};

static struct configfs_item_operations node_ops = {
	.release = release_node,
	.show_attribute = show_node,
	.store_attribute = store_node,
};

static struct config_item_type clusters_type = {
	.ct_group_ops = &clusters_ops,
	.ct_owner = THIS_MODULE,
};

static struct config_item_type cluster_type = {
	.ct_item_ops = &cluster_ops,
391
	.ct_attrs = cluster_attrs,
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
	.ct_owner = THIS_MODULE,
};

static struct config_item_type spaces_type = {
	.ct_group_ops = &spaces_ops,
	.ct_owner = THIS_MODULE,
};

static struct config_item_type space_type = {
	.ct_item_ops = &space_ops,
	.ct_owner = THIS_MODULE,
};

static struct config_item_type comms_type = {
	.ct_group_ops = &comms_ops,
	.ct_owner = THIS_MODULE,
};

static struct config_item_type comm_type = {
	.ct_item_ops = &comm_ops,
	.ct_attrs = comm_attrs,
	.ct_owner = THIS_MODULE,
};

static struct config_item_type nodes_type = {
	.ct_group_ops = &nodes_ops,
	.ct_owner = THIS_MODULE,
};

static struct config_item_type node_type = {
	.ct_item_ops = &node_ops,
	.ct_attrs = node_attrs,
	.ct_owner = THIS_MODULE,
};

A
Andrew Morton 已提交
427
static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
428
{
D
David Teigland 已提交
429 430
	return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
		   NULL;
431 432
}

A
Andrew Morton 已提交
433
static struct dlm_space *config_item_to_space(struct config_item *i)
434
{
D
David Teigland 已提交
435 436
	return i ? container_of(to_config_group(i), struct dlm_space, group) :
		   NULL;
437 438
}

A
Andrew Morton 已提交
439
static struct dlm_comm *config_item_to_comm(struct config_item *i)
440
{
D
David Teigland 已提交
441
	return i ? container_of(i, struct dlm_comm, item) : NULL;
442 443
}

A
Andrew Morton 已提交
444
static struct dlm_node *config_item_to_node(struct config_item *i)
445
{
D
David Teigland 已提交
446
	return i ? container_of(i, struct dlm_node, item) : NULL;
447 448
}

449 450
static struct config_group *make_cluster(struct config_group *g,
					 const char *name)
451
{
D
David Teigland 已提交
452 453 454
	struct dlm_cluster *cl = NULL;
	struct dlm_spaces *sps = NULL;
	struct dlm_comms *cms = NULL;
455 456
	void *gps = NULL;

D
David Teigland 已提交
457 458 459 460
	cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
	gps = kcalloc(3, sizeof(struct config_group *), GFP_NOFS);
	sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
	cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
461 462 463 464 465 466 467 468 469 470 471 472 473

	if (!cl || !gps || !sps || !cms)
		goto fail;

	config_group_init_type_name(&cl->group, name, &cluster_type);
	config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
	config_group_init_type_name(&cms->cs_group, "comms", &comms_type);

	cl->group.default_groups = gps;
	cl->group.default_groups[0] = &sps->ss_group;
	cl->group.default_groups[1] = &cms->cs_group;
	cl->group.default_groups[2] = NULL;

474 475 476 477 478 479 480
	cl->cl_tcp_port = dlm_config.ci_tcp_port;
	cl->cl_buffer_size = dlm_config.ci_buffer_size;
	cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size;
	cl->cl_recover_timer = dlm_config.ci_recover_timer;
	cl->cl_toss_secs = dlm_config.ci_toss_secs;
	cl->cl_scan_secs = dlm_config.ci_scan_secs;
	cl->cl_log_debug = dlm_config.ci_log_debug;
D
David Teigland 已提交
481
	cl->cl_protocol = dlm_config.ci_protocol;
D
David Teigland 已提交
482
	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
483
	cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
D
David Teigland 已提交
484
	cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
D
David Teigland 已提交
485 486 487
	cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
	memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
	       DLM_LOCKSPACE_LEN);
488

489 490
	space_list = &sps->ss_group;
	comm_list = &cms->cs_group;
491
	return &cl->group;
492 493 494 495 496 497

 fail:
	kfree(cl);
	kfree(gps);
	kfree(sps);
	kfree(cms);
498
	return ERR_PTR(-ENOMEM);
499 500 501 502
}

static void drop_cluster(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
503
	struct dlm_cluster *cl = config_item_to_cluster(i);
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
	struct config_item *tmp;
	int j;

	for (j = 0; cl->group.default_groups[j]; j++) {
		tmp = &cl->group.default_groups[j]->cg_item;
		cl->group.default_groups[j] = NULL;
		config_item_put(tmp);
	}

	space_list = NULL;
	comm_list = NULL;

	config_item_put(i);
}

static void release_cluster(struct config_item *i)
{
A
Andrew Morton 已提交
521
	struct dlm_cluster *cl = config_item_to_cluster(i);
522 523 524 525
	kfree(cl->group.default_groups);
	kfree(cl);
}

526
static struct config_group *make_space(struct config_group *g, const char *name)
527
{
D
David Teigland 已提交
528 529
	struct dlm_space *sp = NULL;
	struct dlm_nodes *nds = NULL;
530 531
	void *gps = NULL;

D
David Teigland 已提交
532 533 534
	sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
	gps = kcalloc(2, sizeof(struct config_group *), GFP_NOFS);
	nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
535 536 537 538 539 540 541 542 543 544 545 546

	if (!sp || !gps || !nds)
		goto fail;

	config_group_init_type_name(&sp->group, name, &space_type);
	config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type);

	sp->group.default_groups = gps;
	sp->group.default_groups[0] = &nds->ns_group;
	sp->group.default_groups[1] = NULL;

	INIT_LIST_HEAD(&sp->members);
547
	mutex_init(&sp->members_lock);
548
	sp->members_count = 0;
549
	return &sp->group;
550 551 552 553 554

 fail:
	kfree(sp);
	kfree(gps);
	kfree(nds);
555
	return ERR_PTR(-ENOMEM);
556 557 558 559
}

static void drop_space(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
560
	struct dlm_space *sp = config_item_to_space(i);
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
	struct config_item *tmp;
	int j;

	/* assert list_empty(&sp->members) */

	for (j = 0; sp->group.default_groups[j]; j++) {
		tmp = &sp->group.default_groups[j]->cg_item;
		sp->group.default_groups[j] = NULL;
		config_item_put(tmp);
	}

	config_item_put(i);
}

static void release_space(struct config_item *i)
{
A
Andrew Morton 已提交
577
	struct dlm_space *sp = config_item_to_space(i);
578 579 580 581
	kfree(sp->group.default_groups);
	kfree(sp);
}

582
static struct config_item *make_comm(struct config_group *g, const char *name)
583
{
D
David Teigland 已提交
584
	struct dlm_comm *cm;
585

D
David Teigland 已提交
586
	cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
587
	if (!cm)
588
		return ERR_PTR(-ENOMEM);
589 590

	config_item_init_type_name(&cm->item, name, &comm_type);
D
David Teigland 已提交
591 592 593 594 595

	cm->seq = dlm_comm_count++;
	if (!cm->seq)
		cm->seq = dlm_comm_count++;

596 597 598
	cm->nodeid = -1;
	cm->local = 0;
	cm->addr_count = 0;
599
	return &cm->item;
600 601 602 603
}

static void drop_comm(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
604
	struct dlm_comm *cm = config_item_to_comm(i);
605 606
	if (local_comm == cm)
		local_comm = NULL;
607
	dlm_lowcomms_close(cm->nodeid);
608 609 610 611 612 613 614
	while (cm->addr_count--)
		kfree(cm->addr[cm->addr_count]);
	config_item_put(i);
}

static void release_comm(struct config_item *i)
{
A
Andrew Morton 已提交
615
	struct dlm_comm *cm = config_item_to_comm(i);
616 617 618
	kfree(cm);
}

619
static struct config_item *make_node(struct config_group *g, const char *name)
620
{
A
Andrew Morton 已提交
621
	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
D
David Teigland 已提交
622
	struct dlm_node *nd;
623

D
David Teigland 已提交
624
	nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
625
	if (!nd)
626
		return ERR_PTR(-ENOMEM);
627 628 629 630

	config_item_init_type_name(&nd->item, name, &node_type);
	nd->nodeid = -1;
	nd->weight = 1;  /* default weight of 1 if none is set */
631
	nd->new = 1;     /* set to 0 once it's been read by dlm_nodeid_list() */
632

633
	mutex_lock(&sp->members_lock);
634 635
	list_add(&nd->list, &sp->members);
	sp->members_count++;
636
	mutex_unlock(&sp->members_lock);
637

638
	return &nd->item;
639 640 641 642
}

static void drop_node(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
643 644
	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
	struct dlm_node *nd = config_item_to_node(i);
645

646
	mutex_lock(&sp->members_lock);
647 648
	list_del(&nd->list);
	sp->members_count--;
649
	mutex_unlock(&sp->members_lock);
650 651 652 653 654 655

	config_item_put(i);
}

static void release_node(struct config_item *i)
{
A
Andrew Morton 已提交
656
	struct dlm_node *nd = config_item_to_node(i);
657 658 659
	kfree(nd);
}

D
David Teigland 已提交
660
static struct dlm_clusters clusters_root = {
661 662 663 664 665 666 667 668 669 670
	.subsys = {
		.su_group = {
			.cg_item = {
				.ci_namebuf = "dlm",
				.ci_type = &clusters_type,
			},
		},
	},
};

671
int __init dlm_config_init(void)
672 673
{
	config_group_init(&clusters_root.subsys.su_group);
674
	mutex_init(&clusters_root.subsys.su_mutex);
675 676 677 678 679 680 681 682 683 684 685 686
	return configfs_register_subsystem(&clusters_root.subsys);
}

void dlm_config_exit(void)
{
	configfs_unregister_subsystem(&clusters_root.subsys);
}

/*
 * Functions for user space to read/write attributes
 */

687 688 689
static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
			    char *buf)
{
A
Andrew Morton 已提交
690
	struct dlm_cluster *cl = config_item_to_cluster(i);
691 692 693 694 695 696 697 698 699
	struct cluster_attribute *cla =
			container_of(a, struct cluster_attribute, attr);
	return cla->show ? cla->show(cl, buf) : 0;
}

static ssize_t store_cluster(struct config_item *i,
			     struct configfs_attribute *a,
			     const char *buf, size_t len)
{
A
Andrew Morton 已提交
700
	struct dlm_cluster *cl = config_item_to_cluster(i);
701 702 703 704 705
	struct cluster_attribute *cla =
		container_of(a, struct cluster_attribute, attr);
	return cla->store ? cla->store(cl, buf, len) : -EINVAL;
}

706 707 708
static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
			 char *buf)
{
A
Andrew Morton 已提交
709
	struct dlm_comm *cm = config_item_to_comm(i);
710 711 712 713 714 715 716 717
	struct comm_attribute *cma =
			container_of(a, struct comm_attribute, attr);
	return cma->show ? cma->show(cm, buf) : 0;
}

static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
			  const char *buf, size_t len)
{
A
Andrew Morton 已提交
718
	struct dlm_comm *cm = config_item_to_comm(i);
719 720 721 722 723
	struct comm_attribute *cma =
		container_of(a, struct comm_attribute, attr);
	return cma->store ? cma->store(cm, buf, len) : -EINVAL;
}

D
David Teigland 已提交
724
static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf)
725 726 727 728
{
	return sprintf(buf, "%d\n", cm->nodeid);
}

D
David Teigland 已提交
729 730
static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
				 size_t len)
731 732 733 734 735
{
	cm->nodeid = simple_strtol(buf, NULL, 0);
	return len;
}

D
David Teigland 已提交
736
static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
737 738 739 740
{
	return sprintf(buf, "%d\n", cm->local);
}

D
David Teigland 已提交
741 742
static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
				size_t len)
743 744 745 746 747 748 749
{
	cm->local= simple_strtol(buf, NULL, 0);
	if (cm->local && !local_comm)
		local_comm = cm;
	return len;
}

D
David Teigland 已提交
750
static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
751 752
{
	struct sockaddr_storage *addr;
753
	int rv;
754 755 756 757 758 759 760

	if (len != sizeof(struct sockaddr_storage))
		return -EINVAL;

	if (cm->addr_count >= DLM_MAX_ADDR_COUNT)
		return -ENOSPC;

D
David Teigland 已提交
761
	addr = kzalloc(sizeof(*addr), GFP_NOFS);
762 763 764 765
	if (!addr)
		return -ENOMEM;

	memcpy(addr, buf, len);
766 767 768 769 770 771 772

	rv = dlm_lowcomms_addr(cm->nodeid, addr, len);
	if (rv) {
		kfree(addr);
		return rv;
	}

773 774 775 776
	cm->addr[cm->addr_count++] = addr;
	return len;
}

777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf)
{
	ssize_t s;
	ssize_t allowance;
	int i;
	struct sockaddr_storage *addr;
	struct sockaddr_in *addr_in;
	struct sockaddr_in6 *addr_in6;
	
	/* Taken from ip6_addr_string() defined in lib/vsprintf.c */
	char buf0[sizeof("AF_INET6	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255\n")];
	

	/* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */
	allowance = 4096;
	buf[0] = '\0';

	for (i = 0; i < cm->addr_count; i++) {
		addr = cm->addr[i];

		switch(addr->ss_family) {
		case AF_INET:
			addr_in = (struct sockaddr_in *)addr;
			s = sprintf(buf0, "AF_INET	%pI4\n", &addr_in->sin_addr.s_addr);
			break;
		case AF_INET6:
			addr_in6 = (struct sockaddr_in6 *)addr;
			s = sprintf(buf0, "AF_INET6	%pI6\n", &addr_in6->sin6_addr);
			break;
		default:
			s = sprintf(buf0, "%s\n", "<UNKNOWN>");
			break;
		}
		allowance -= s;
		if (allowance >= 0)
			strcat(buf, buf0);
		else {
			allowance += s;
			break;
		}
	}
	return 4096 - allowance;
}

821 822 823
static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
			 char *buf)
{
A
Andrew Morton 已提交
824
	struct dlm_node *nd = config_item_to_node(i);
825 826 827 828 829 830 831 832
	struct node_attribute *nda =
			container_of(a, struct node_attribute, attr);
	return nda->show ? nda->show(nd, buf) : 0;
}

static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
			  const char *buf, size_t len)
{
A
Andrew Morton 已提交
833
	struct dlm_node *nd = config_item_to_node(i);
834 835 836 837 838
	struct node_attribute *nda =
		container_of(a, struct node_attribute, attr);
	return nda->store ? nda->store(nd, buf, len) : -EINVAL;
}

D
David Teigland 已提交
839
static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
840 841 842 843
{
	return sprintf(buf, "%d\n", nd->nodeid);
}

D
David Teigland 已提交
844 845
static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
				 size_t len)
846
{
D
David Teigland 已提交
847
	uint32_t seq = 0;
848
	nd->nodeid = simple_strtol(buf, NULL, 0);
D
David Teigland 已提交
849 850
	dlm_comm_seq(nd->nodeid, &seq);
	nd->comm_seq = seq;
851 852 853
	return len;
}

D
David Teigland 已提交
854
static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
855 856 857 858
{
	return sprintf(buf, "%d\n", nd->weight);
}

D
David Teigland 已提交
859 860
static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
				 size_t len)
861 862 863 864 865 866 867 868 869
{
	nd->weight = simple_strtol(buf, NULL, 0);
	return len;
}

/*
 * Functions for the dlm to get the info that's been configured
 */

D
David Teigland 已提交
870
static struct dlm_space *get_space(char *name)
871
{
S
Satyam Sharma 已提交
872 873
	struct config_item *i;

874 875
	if (!space_list)
		return NULL;
S
Satyam Sharma 已提交
876

877
	mutex_lock(&space_list->cg_subsys->su_mutex);
878
	i = config_group_find_item(space_list, name);
879
	mutex_unlock(&space_list->cg_subsys->su_mutex);
S
Satyam Sharma 已提交
880

A
Andrew Morton 已提交
881
	return config_item_to_space(i);
882 883
}

D
David Teigland 已提交
884
static void put_space(struct dlm_space *sp)
885 886 887 888
{
	config_item_put(&sp->group.cg_item);
}

889
static struct dlm_comm *get_comm(int nodeid)
890 891
{
	struct config_item *i;
D
David Teigland 已提交
892
	struct dlm_comm *cm = NULL;
893 894 895 896 897
	int found = 0;

	if (!comm_list)
		return NULL;

898
	mutex_lock(&clusters_root.subsys.su_mutex);
899 900

	list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
A
Andrew Morton 已提交
901
		cm = config_item_to_comm(i);
902

903 904 905 906 907
		if (cm->nodeid != nodeid)
			continue;
		found = 1;
		config_item_get(i);
		break;
908
	}
909
	mutex_unlock(&clusters_root.subsys.su_mutex);
910

S
Satyam Sharma 已提交
911
	if (!found)
912 913 914 915
		cm = NULL;
	return cm;
}

D
David Teigland 已提交
916
static void put_comm(struct dlm_comm *cm)
917 918 919 920 921
{
	config_item_put(&cm->item);
}

/* caller must free mem */
D
David Teigland 已提交
922 923
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
		     int *count_out)
924
{
D
David Teigland 已提交
925 926
	struct dlm_space *sp;
	struct dlm_node *nd;
D
David Teigland 已提交
927 928
	struct dlm_config_node *nodes, *node;
	int rv, count;
929 930 931 932 933

	sp = get_space(lsname);
	if (!sp)
		return -EEXIST;

934
	mutex_lock(&sp->members_lock);
935
	if (!sp->members_count) {
936 937
		rv = -EINVAL;
		printk(KERN_ERR "dlm: zero members_count\n");
938 939 940
		goto out;
	}

D
David Teigland 已提交
941
	count = sp->members_count;
942

D
David Teigland 已提交
943 944
	nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
	if (!nodes) {
945 946 947 948
		rv = -ENOMEM;
		goto out;
	}

D
David Teigland 已提交
949
	node = nodes;
950
	list_for_each_entry(nd, &sp->members, list) {
D
David Teigland 已提交
951 952 953 954 955
		node->nodeid = nd->nodeid;
		node->weight = nd->weight;
		node->new = nd->new;
		node->comm_seq = nd->comm_seq;
		node++;
956

D
David Teigland 已提交
957
		nd->new = 0;
958
	}
959

D
David Teigland 已提交
960 961 962
	*count_out = count;
	*nodes_out = nodes;
	rv = 0;
963
 out:
964
	mutex_unlock(&sp->members_lock);
965 966 967 968
	put_space(sp);
	return rv;
}

D
David Teigland 已提交
969
int dlm_comm_seq(int nodeid, uint32_t *seq)
970
{
971
	struct dlm_comm *cm = get_comm(nodeid);
D
David Teigland 已提交
972 973 974 975 976
	if (!cm)
		return -EEXIST;
	*seq = cm->seq;
	put_comm(cm);
	return 0;
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
}

int dlm_our_nodeid(void)
{
	return local_comm ? local_comm->nodeid : 0;
}

/* num 0 is first addr, num 1 is second addr */
int dlm_our_addr(struct sockaddr_storage *addr, int num)
{
	if (!local_comm)
		return -1;
	if (num + 1 > local_comm->addr_count)
		return -1;
	memcpy(addr, local_comm->addr[num], sizeof(*addr));
	return 0;
}

/* Config file defaults */
#define DEFAULT_TCP_PORT       21064
#define DEFAULT_BUFFER_SIZE     4096
998
#define DEFAULT_RSBTBL_SIZE     1024
999 1000 1001
#define DEFAULT_RECOVER_TIMER      5
#define DEFAULT_TOSS_SECS         10
#define DEFAULT_SCAN_SECS          5
1002
#define DEFAULT_LOG_DEBUG          0
1003
#define DEFAULT_PROTOCOL           0
1004
#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
1005
#define DEFAULT_WAITWARN_US	   0
D
David Teigland 已提交
1006
#define DEFAULT_NEW_RSB_COUNT    128
D
David Teigland 已提交
1007 1008
#define DEFAULT_RECOVER_CALLBACKS  0
#define DEFAULT_CLUSTER_NAME      ""
1009 1010

struct dlm_config_info dlm_config = {
1011 1012 1013 1014 1015
	.ci_tcp_port = DEFAULT_TCP_PORT,
	.ci_buffer_size = DEFAULT_BUFFER_SIZE,
	.ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
	.ci_recover_timer = DEFAULT_RECOVER_TIMER,
	.ci_toss_secs = DEFAULT_TOSS_SECS,
1016
	.ci_scan_secs = DEFAULT_SCAN_SECS,
1017
	.ci_log_debug = DEFAULT_LOG_DEBUG,
1018
	.ci_protocol = DEFAULT_PROTOCOL,
1019
	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
D
David Teigland 已提交
1020
	.ci_waitwarn_us = DEFAULT_WAITWARN_US,
D
David Teigland 已提交
1021 1022 1023
	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
	.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
	.ci_cluster_name = DEFAULT_CLUSTER_NAME
1024 1025
};