config.c 21.4 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
static struct configfs_attribute *comm_attrs[];
static struct configfs_attribute *node_attrs[];
D
David Teigland 已提交
66 67

struct dlm_cluster {
68 69 70 71 72 73 74 75
	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;
76
	unsigned int cl_protocol;
77
	unsigned int cl_timewarn_cs;
78
	unsigned int cl_waitwarn_us;
D
David Teigland 已提交
79
	unsigned int cl_new_rsb_count;
D
David Teigland 已提交
80 81
	unsigned int cl_recover_callbacks;
	char cl_cluster_name[DLM_LOCKSPACE_LEN];
82 83
};

84 85 86 87 88 89
static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
{
	return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
		   NULL;
}

90 91 92 93 94 95 96 97
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,
98
	CLUSTER_ATTR_PROTOCOL,
99
	CLUSTER_ATTR_TIMEWARN_CS,
100
	CLUSTER_ATTR_WAITWARN_US,
D
David Teigland 已提交
101
	CLUSTER_ATTR_NEW_RSB_COUNT,
D
David Teigland 已提交
102 103
	CLUSTER_ATTR_RECOVER_CALLBACKS,
	CLUSTER_ATTR_CLUSTER_NAME,
104 105
};

106
static ssize_t cluster_cluster_name_show(struct config_item *item, char *buf)
D
David Teigland 已提交
107
{
108
	struct dlm_cluster *cl = config_item_to_cluster(item);
D
David Teigland 已提交
109 110 111
	return sprintf(buf, "%s\n", cl->cl_cluster_name);
}

112
static ssize_t cluster_cluster_name_store(struct config_item *item,
D
David Teigland 已提交
113 114
					  const char *buf, size_t len)
{
115 116
	struct dlm_cluster *cl = config_item_to_cluster(item);

117 118 119
	strlcpy(dlm_config.ci_cluster_name, buf,
				sizeof(dlm_config.ci_cluster_name));
	strlcpy(cl->cl_cluster_name, buf, sizeof(cl->cl_cluster_name));
D
David Teigland 已提交
120 121 122
	return len;
}

123
CONFIGFS_ATTR(cluster_, cluster_name);
D
David Teigland 已提交
124

D
David Teigland 已提交
125
static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
126
			   int *info_field, int check_zero,
127 128 129
			   const char *buf, size_t len)
{
	unsigned int x;
130
	int rc;
131 132

	if (!capable(CAP_SYS_ADMIN))
133
		return -EPERM;
134 135 136
	rc = kstrtouint(buf, 0, &x);
	if (rc)
		return rc;
137 138 139 140 141 142 143 144 145 146 147

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

	*cl_field = x;
	*info_field = x;

	return len;
}

#define CLUSTER_ATTR(name, check_zero)                                        \
148 149
static ssize_t cluster_##name##_store(struct config_item *item, \
		const char *buf, size_t len) \
150
{                                                                             \
151
	struct dlm_cluster *cl = config_item_to_cluster(item);		      \
152 153 154
	return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
			   check_zero, buf, len);                             \
}                                                                             \
155
static ssize_t cluster_##name##_show(struct config_item *item, char *buf)     \
156
{                                                                             \
157
	struct dlm_cluster *cl = config_item_to_cluster(item);		      \
158 159
	return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
}                                                                             \
160
CONFIGFS_ATTR(cluster_, name);
161 162 163 164 165 166 167 168

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);
169
CLUSTER_ATTR(protocol, 0);
170
CLUSTER_ATTR(timewarn_cs, 1);
171
CLUSTER_ATTR(waitwarn_us, 0);
D
David Teigland 已提交
172
CLUSTER_ATTR(new_rsb_count, 0);
D
David Teigland 已提交
173
CLUSTER_ATTR(recover_callbacks, 0);
174 175

static struct configfs_attribute *cluster_attrs[] = {
176 177 178 179 180 181 182 183 184 185 186 187 188
	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port,
	[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size,
	[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size,
	[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer,
	[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs,
	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs,
	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug,
	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol,
	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs,
	[CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us,
	[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count,
	[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks,
	[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name,
189 190 191
	NULL,
};

192 193 194 195
enum {
	COMM_ATTR_NODEID = 0,
	COMM_ATTR_LOCAL,
	COMM_ATTR_ADDR,
196
	COMM_ATTR_ADDR_LIST,
197 198 199 200 201 202 203
};

enum {
	NODE_ATTR_NODEID = 0,
	NODE_ATTR_WEIGHT,
};

D
David Teigland 已提交
204
struct dlm_clusters {
205 206 207
	struct configfs_subsystem subsys;
};

D
David Teigland 已提交
208
struct dlm_spaces {
209 210 211
	struct config_group ss_group;
};

D
David Teigland 已提交
212
struct dlm_space {
213 214
	struct config_group group;
	struct list_head members;
215
	struct mutex members_lock;
216 217 218
	int members_count;
};

D
David Teigland 已提交
219
struct dlm_comms {
220 221 222
	struct config_group cs_group;
};

D
David Teigland 已提交
223
struct dlm_comm {
224
	struct config_item item;
D
David Teigland 已提交
225
	int seq;
226 227 228 229 230 231
	int nodeid;
	int local;
	int addr_count;
	struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
};

D
David Teigland 已提交
232
struct dlm_nodes {
233 234 235
	struct config_group ns_group;
};

D
David Teigland 已提交
236
struct dlm_node {
237 238 239 240
	struct config_item item;
	struct list_head list; /* space->members */
	int nodeid;
	int weight;
241
	int new;
D
David Teigland 已提交
242
	int comm_seq; /* copy of cm->seq when nd->nodeid is set */
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
};

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,
};

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,
};

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,
};

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,
288
	.ct_attrs = cluster_attrs,
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
	.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 已提交
324
static struct dlm_space *config_item_to_space(struct config_item *i)
325
{
D
David Teigland 已提交
326 327
	return i ? container_of(to_config_group(i), struct dlm_space, group) :
		   NULL;
328 329
}

A
Andrew Morton 已提交
330
static struct dlm_comm *config_item_to_comm(struct config_item *i)
331
{
D
David Teigland 已提交
332
	return i ? container_of(i, struct dlm_comm, item) : NULL;
333 334
}

A
Andrew Morton 已提交
335
static struct dlm_node *config_item_to_node(struct config_item *i)
336
{
D
David Teigland 已提交
337
	return i ? container_of(i, struct dlm_node, item) : NULL;
338 339
}

340 341
static struct config_group *make_cluster(struct config_group *g,
					 const char *name)
342
{
D
David Teigland 已提交
343 344 345
	struct dlm_cluster *cl = NULL;
	struct dlm_spaces *sps = NULL;
	struct dlm_comms *cms = NULL;
346 347
	void *gps = NULL;

D
David Teigland 已提交
348 349 350
	cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
	sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
	cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
351 352 353 354 355 356 357 358

	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);

359 360
	configfs_add_default_group(&sps->ss_group, &cl->group);
	configfs_add_default_group(&cms->cs_group, &cl->group);
361

362 363 364 365 366 367 368
	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 已提交
369
	cl->cl_protocol = dlm_config.ci_protocol;
D
David Teigland 已提交
370
	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
371
	cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
D
David Teigland 已提交
372
	cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
D
David Teigland 已提交
373 374 375
	cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
	memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
	       DLM_LOCKSPACE_LEN);
376

377 378
	space_list = &sps->ss_group;
	comm_list = &cms->cs_group;
379
	return &cl->group;
380 381 382 383 384

 fail:
	kfree(cl);
	kfree(sps);
	kfree(cms);
385
	return ERR_PTR(-ENOMEM);
386 387 388 389
}

static void drop_cluster(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
390
	struct dlm_cluster *cl = config_item_to_cluster(i);
391

392
	configfs_remove_default_groups(&cl->group);
393 394 395 396 397 398 399 400 401

	space_list = NULL;
	comm_list = NULL;

	config_item_put(i);
}

static void release_cluster(struct config_item *i)
{
A
Andrew Morton 已提交
402
	struct dlm_cluster *cl = config_item_to_cluster(i);
403 404 405
	kfree(cl);
}

406
static struct config_group *make_space(struct config_group *g, const char *name)
407
{
D
David Teigland 已提交
408 409
	struct dlm_space *sp = NULL;
	struct dlm_nodes *nds = NULL;
410

D
David Teigland 已提交
411 412
	sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
	nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
413

414
	if (!sp || !nds)
415 416 417 418
		goto fail;

	config_group_init_type_name(&sp->group, name, &space_type);

419 420
	config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type);
	configfs_add_default_group(&nds->ns_group, &sp->group);
421 422

	INIT_LIST_HEAD(&sp->members);
423
	mutex_init(&sp->members_lock);
424
	sp->members_count = 0;
425
	return &sp->group;
426 427 428 429

 fail:
	kfree(sp);
	kfree(nds);
430
	return ERR_PTR(-ENOMEM);
431 432 433 434
}

static void drop_space(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
435
	struct dlm_space *sp = config_item_to_space(i);
436 437 438

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

439
	configfs_remove_default_groups(&sp->group);
440 441 442 443 444
	config_item_put(i);
}

static void release_space(struct config_item *i)
{
A
Andrew Morton 已提交
445
	struct dlm_space *sp = config_item_to_space(i);
446 447 448
	kfree(sp);
}

449
static struct config_item *make_comm(struct config_group *g, const char *name)
450
{
D
David Teigland 已提交
451
	struct dlm_comm *cm;
452

D
David Teigland 已提交
453
	cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
454
	if (!cm)
455
		return ERR_PTR(-ENOMEM);
456 457

	config_item_init_type_name(&cm->item, name, &comm_type);
D
David Teigland 已提交
458 459 460 461 462

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

463 464 465
	cm->nodeid = -1;
	cm->local = 0;
	cm->addr_count = 0;
466
	return &cm->item;
467 468 469 470
}

static void drop_comm(struct config_group *g, struct config_item *i)
{
A
Andrew Morton 已提交
471
	struct dlm_comm *cm = config_item_to_comm(i);
472 473
	if (local_comm == cm)
		local_comm = NULL;
474
	dlm_lowcomms_close(cm->nodeid);
475 476 477 478 479 480 481
	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 已提交
482
	struct dlm_comm *cm = config_item_to_comm(i);
483 484 485
	kfree(cm);
}

486
static struct config_item *make_node(struct config_group *g, const char *name)
487
{
A
Andrew Morton 已提交
488
	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
D
David Teigland 已提交
489
	struct dlm_node *nd;
490

D
David Teigland 已提交
491
	nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
492
	if (!nd)
493
		return ERR_PTR(-ENOMEM);
494 495 496 497

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

500
	mutex_lock(&sp->members_lock);
501 502
	list_add(&nd->list, &sp->members);
	sp->members_count++;
503
	mutex_unlock(&sp->members_lock);
504

505
	return &nd->item;
506 507 508 509
}

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

513
	mutex_lock(&sp->members_lock);
514 515
	list_del(&nd->list);
	sp->members_count--;
516
	mutex_unlock(&sp->members_lock);
517 518 519 520 521 522

	config_item_put(i);
}

static void release_node(struct config_item *i)
{
A
Andrew Morton 已提交
523
	struct dlm_node *nd = config_item_to_node(i);
524 525 526
	kfree(nd);
}

D
David Teigland 已提交
527
static struct dlm_clusters clusters_root = {
528 529 530 531 532 533 534 535 536 537
	.subsys = {
		.su_group = {
			.cg_item = {
				.ci_namebuf = "dlm",
				.ci_type = &clusters_type,
			},
		},
	},
};

538
int __init dlm_config_init(void)
539 540
{
	config_group_init(&clusters_root.subsys.su_group);
541
	mutex_init(&clusters_root.subsys.su_mutex);
542 543 544 545 546 547 548 549 550 551 552 553
	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
 */

554
static ssize_t comm_nodeid_show(struct config_item *item, char *buf)
555
{
556
	return sprintf(buf, "%d\n", config_item_to_comm(item)->nodeid);
557 558
}

559
static ssize_t comm_nodeid_store(struct config_item *item, const char *buf,
D
David Teigland 已提交
560
				 size_t len)
561
{
562
	int rc = kstrtoint(buf, 0, &config_item_to_comm(item)->nodeid);
563 564 565

	if (rc)
		return rc;
566 567 568
	return len;
}

569
static ssize_t comm_local_show(struct config_item *item, char *buf)
570
{
571
	return sprintf(buf, "%d\n", config_item_to_comm(item)->local);
572 573
}

574
static ssize_t comm_local_store(struct config_item *item, const char *buf,
D
David Teigland 已提交
575
				size_t len)
576
{
577
	struct dlm_comm *cm = config_item_to_comm(item);
578 579 580 581
	int rc = kstrtoint(buf, 0, &cm->local);

	if (rc)
		return rc;
582 583 584 585 586
	if (cm->local && !local_comm)
		local_comm = cm;
	return len;
}

587 588
static ssize_t comm_addr_store(struct config_item *item, const char *buf,
		size_t len)
589
{
590
	struct dlm_comm *cm = config_item_to_comm(item);
591
	struct sockaddr_storage *addr;
592
	int rv;
593 594 595 596 597 598 599

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

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

D
David Teigland 已提交
600
	addr = kzalloc(sizeof(*addr), GFP_NOFS);
601 602 603 604
	if (!addr)
		return -ENOMEM;

	memcpy(addr, buf, len);
605 606 607 608 609 610 611

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

612 613 614 615
	cm->addr[cm->addr_count++] = addr;
	return len;
}

616
static ssize_t comm_addr_list_show(struct config_item *item, char *buf)
617
{
618
	struct dlm_comm *cm = config_item_to_comm(item);
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
	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;
}

661 662 663 664
CONFIGFS_ATTR(comm_, nodeid);
CONFIGFS_ATTR(comm_, local);
CONFIGFS_ATTR_WO(comm_, addr);
CONFIGFS_ATTR_RO(comm_, addr_list);
665

666 667 668 669 670 671 672
static struct configfs_attribute *comm_attrs[] = {
	[COMM_ATTR_NODEID] = &comm_attr_nodeid,
	[COMM_ATTR_LOCAL] = &comm_attr_local,
	[COMM_ATTR_ADDR] = &comm_attr_addr,
	[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list,
	NULL,
};
673

674
static ssize_t node_nodeid_show(struct config_item *item, char *buf)
675
{
676
	return sprintf(buf, "%d\n", config_item_to_node(item)->nodeid);
677 678
}

679
static ssize_t node_nodeid_store(struct config_item *item, const char *buf,
D
David Teigland 已提交
680
				 size_t len)
681
{
682
	struct dlm_node *nd = config_item_to_node(item);
D
David Teigland 已提交
683
	uint32_t seq = 0;
684 685 686 687
	int rc = kstrtoint(buf, 0, &nd->nodeid);

	if (rc)
		return rc;
D
David Teigland 已提交
688 689
	dlm_comm_seq(nd->nodeid, &seq);
	nd->comm_seq = seq;
690 691 692
	return len;
}

693
static ssize_t node_weight_show(struct config_item *item, char *buf)
694
{
695
	return sprintf(buf, "%d\n", config_item_to_node(item)->weight);
696 697
}

698
static ssize_t node_weight_store(struct config_item *item, const char *buf,
D
David Teigland 已提交
699
				 size_t len)
700
{
701
	int rc = kstrtoint(buf, 0, &config_item_to_node(item)->weight);
702 703 704

	if (rc)
		return rc;
705 706 707
	return len;
}

708 709 710 711 712 713 714 715 716
CONFIGFS_ATTR(node_, nodeid);
CONFIGFS_ATTR(node_, weight);

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

717 718 719 720
/*
 * Functions for the dlm to get the info that's been configured
 */

D
David Teigland 已提交
721
static struct dlm_space *get_space(char *name)
722
{
S
Satyam Sharma 已提交
723 724
	struct config_item *i;

725 726
	if (!space_list)
		return NULL;
S
Satyam Sharma 已提交
727

728
	mutex_lock(&space_list->cg_subsys->su_mutex);
729
	i = config_group_find_item(space_list, name);
730
	mutex_unlock(&space_list->cg_subsys->su_mutex);
S
Satyam Sharma 已提交
731

A
Andrew Morton 已提交
732
	return config_item_to_space(i);
733 734
}

D
David Teigland 已提交
735
static void put_space(struct dlm_space *sp)
736 737 738 739
{
	config_item_put(&sp->group.cg_item);
}

740
static struct dlm_comm *get_comm(int nodeid)
741 742
{
	struct config_item *i;
D
David Teigland 已提交
743
	struct dlm_comm *cm = NULL;
744 745 746 747 748
	int found = 0;

	if (!comm_list)
		return NULL;

749
	mutex_lock(&clusters_root.subsys.su_mutex);
750 751

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

754 755 756 757 758
		if (cm->nodeid != nodeid)
			continue;
		found = 1;
		config_item_get(i);
		break;
759
	}
760
	mutex_unlock(&clusters_root.subsys.su_mutex);
761

S
Satyam Sharma 已提交
762
	if (!found)
763 764 765 766
		cm = NULL;
	return cm;
}

D
David Teigland 已提交
767
static void put_comm(struct dlm_comm *cm)
768 769 770 771 772
{
	config_item_put(&cm->item);
}

/* caller must free mem */
D
David Teigland 已提交
773 774
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
		     int *count_out)
775
{
D
David Teigland 已提交
776 777
	struct dlm_space *sp;
	struct dlm_node *nd;
D
David Teigland 已提交
778 779
	struct dlm_config_node *nodes, *node;
	int rv, count;
780 781 782 783 784

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

785
	mutex_lock(&sp->members_lock);
786
	if (!sp->members_count) {
787 788
		rv = -EINVAL;
		printk(KERN_ERR "dlm: zero members_count\n");
789 790 791
		goto out;
	}

D
David Teigland 已提交
792
	count = sp->members_count;
793

D
David Teigland 已提交
794 795
	nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
	if (!nodes) {
796 797 798 799
		rv = -ENOMEM;
		goto out;
	}

D
David Teigland 已提交
800
	node = nodes;
801
	list_for_each_entry(nd, &sp->members, list) {
D
David Teigland 已提交
802 803 804 805 806
		node->nodeid = nd->nodeid;
		node->weight = nd->weight;
		node->new = nd->new;
		node->comm_seq = nd->comm_seq;
		node++;
807

D
David Teigland 已提交
808
		nd->new = 0;
809
	}
810

D
David Teigland 已提交
811 812 813
	*count_out = count;
	*nodes_out = nodes;
	rv = 0;
814
 out:
815
	mutex_unlock(&sp->members_lock);
816 817 818 819
	put_space(sp);
	return rv;
}

D
David Teigland 已提交
820
int dlm_comm_seq(int nodeid, uint32_t *seq)
821
{
822
	struct dlm_comm *cm = get_comm(nodeid);
D
David Teigland 已提交
823 824 825 826 827
	if (!cm)
		return -EEXIST;
	*seq = cm->seq;
	put_comm(cm);
	return 0;
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
}

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
849
#define DEFAULT_RSBTBL_SIZE     1024
850 851 852
#define DEFAULT_RECOVER_TIMER      5
#define DEFAULT_TOSS_SECS         10
#define DEFAULT_SCAN_SECS          5
853
#define DEFAULT_LOG_DEBUG          0
854
#define DEFAULT_PROTOCOL           0
855
#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
856
#define DEFAULT_WAITWARN_US	   0
D
David Teigland 已提交
857
#define DEFAULT_NEW_RSB_COUNT    128
D
David Teigland 已提交
858 859
#define DEFAULT_RECOVER_CALLBACKS  0
#define DEFAULT_CLUSTER_NAME      ""
860 861

struct dlm_config_info dlm_config = {
862 863 864 865 866
	.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,
867
	.ci_scan_secs = DEFAULT_SCAN_SECS,
868
	.ci_log_debug = DEFAULT_LOG_DEBUG,
869
	.ci_protocol = DEFAULT_PROTOCOL,
870
	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
D
David Teigland 已提交
871
	.ci_waitwarn_us = DEFAULT_WAITWARN_US,
D
David Teigland 已提交
872 873 874
	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
	.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
	.ci_cluster_name = DEFAULT_CLUSTER_NAME
875 876
};