config.c 26.7 KB
Newer Older
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 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>
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;
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;
106
	unsigned int cl_new_rsb_count;
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,
122
	CLUSTER_ATTR_NEW_RSB_COUNT,
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
};

133 134 135 136 137 138 139 140
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)
{
141 142 143
	strlcpy(dlm_config.ci_cluster_name, buf,
				sizeof(dlm_config.ci_cluster_name));
	strlcpy(cl->cl_cluster_name, buf, sizeof(cl->cl_cluster_name));
144 145 146 147 148 149 150 151 152 153 154
	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 已提交
155
static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
156
			   int *info_field, int check_zero,
157 158 159
			   const char *buf, size_t len)
{
	unsigned int x;
160
	int rc;
161 162

	if (!capable(CAP_SYS_ADMIN))
163
		return -EPERM;
164 165 166
	rc = kstrtouint(buf, 0, &x);
	if (rc)
		return rc;
167 168 169 170 171 172 173 174 175 176 177

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

	*cl_field = x;
	*info_field = x;

	return len;
}

#define CLUSTER_ATTR(name, check_zero)                                        \
D
David Teigland 已提交
178
static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \
179 180 181 182
{                                                                             \
	return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
			   check_zero, buf, len);                             \
}                                                                             \
D
David Teigland 已提交
183
static ssize_t name##_read(struct dlm_cluster *cl, char *buf)                 \
184 185 186 187 188 189 190 191 192 193 194 195 196
{                                                                             \
	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);
197
CLUSTER_ATTR(protocol, 0);
198
CLUSTER_ATTR(timewarn_cs, 1);
199
CLUSTER_ATTR(waitwarn_us, 0);
200
CLUSTER_ATTR(new_rsb_count, 0);
201
CLUSTER_ATTR(recover_callbacks, 0);
202 203 204 205 206 207 208 209 210

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,
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 216
	[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr,
	[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr,
217 218 219
	NULL,
};

220 221 222 223
enum {
	COMM_ATTR_NODEID = 0,
	COMM_ATTR_LOCAL,
	COMM_ATTR_ADDR,
224
	COMM_ATTR_ADDR_LIST,
225 226 227 228
};

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

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",
252
                    .ca_mode = S_IWUSR },
253 254 255
	.store  = comm_addr_write,
};

256 257 258 259 260 261 262
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,
};

263 264 265 266
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,
267
	[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list.attr,
268 269 270 271 272 273 274 275 276 277
	NULL,
};

enum {
	NODE_ATTR_NODEID = 0,
	NODE_ATTR_WEIGHT,
};

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

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 已提交
304
struct dlm_clusters {
305 306 307
	struct configfs_subsystem subsys;
};

D
David Teigland 已提交
308
struct dlm_spaces {
309 310 311
	struct config_group ss_group;
};

D
David Teigland 已提交
312
struct dlm_space {
313 314
	struct config_group group;
	struct list_head members;
315
	struct mutex members_lock;
316 317 318
	int members_count;
};

D
David Teigland 已提交
319
struct dlm_comms {
320 321 322
	struct config_group cs_group;
};

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

D
David Teigland 已提交
332
struct dlm_nodes {
333 334 335
	struct config_group ns_group;
};

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

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,
352 353
	.show_attribute = show_cluster,
	.store_attribute = store_cluster,
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 391 392 393
};

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,
394
	.ct_attrs = cluster_attrs,
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 427 428 429
	.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,
};

430
static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
431
{
D
David Teigland 已提交
432 433
	return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
		   NULL;
434 435
}

436
static struct dlm_space *config_item_to_space(struct config_item *i)
437
{
D
David Teigland 已提交
438 439
	return i ? container_of(to_config_group(i), struct dlm_space, group) :
		   NULL;
440 441
}

442
static struct dlm_comm *config_item_to_comm(struct config_item *i)
443
{
D
David Teigland 已提交
444
	return i ? container_of(i, struct dlm_comm, item) : NULL;
445 446
}

447
static struct dlm_node *config_item_to_node(struct config_item *i)
448
{
D
David Teigland 已提交
449
	return i ? container_of(i, struct dlm_node, item) : NULL;
450 451
}

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

D
David Teigland 已提交
460 461 462 463
	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);
464 465 466 467 468 469 470 471 472 473 474 475 476

	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;

477 478 479 480 481 482 483
	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;
484
	cl->cl_protocol = dlm_config.ci_protocol;
D
David Teigland 已提交
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 489 490
	cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
	memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
	       DLM_LOCKSPACE_LEN);
491

492 493
	space_list = &sps->ss_group;
	comm_list = &cms->cs_group;
494
	return &cl->group;
495 496 497 498 499 500

 fail:
	kfree(cl);
	kfree(gps);
	kfree(sps);
	kfree(cms);
501
	return ERR_PTR(-ENOMEM);
502 503 504 505
}

static void drop_cluster(struct config_group *g, struct config_item *i)
{
506
	struct dlm_cluster *cl = config_item_to_cluster(i);
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
	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)
{
524
	struct dlm_cluster *cl = config_item_to_cluster(i);
525 526 527 528
	kfree(cl->group.default_groups);
	kfree(cl);
}

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

D
David Teigland 已提交
535 536 537
	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);
538 539 540 541 542 543 544 545 546 547 548 549

	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);
550
	mutex_init(&sp->members_lock);
551
	sp->members_count = 0;
552
	return &sp->group;
553 554 555 556 557

 fail:
	kfree(sp);
	kfree(gps);
	kfree(nds);
558
	return ERR_PTR(-ENOMEM);
559 560 561 562
}

static void drop_space(struct config_group *g, struct config_item *i)
{
563
	struct dlm_space *sp = config_item_to_space(i);
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
	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)
{
580
	struct dlm_space *sp = config_item_to_space(i);
581 582 583 584
	kfree(sp->group.default_groups);
	kfree(sp);
}

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

D
David Teigland 已提交
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 596 597 598

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

599 600 601
	cm->nodeid = -1;
	cm->local = 0;
	cm->addr_count = 0;
602
	return &cm->item;
603 604 605 606
}

static void drop_comm(struct config_group *g, struct config_item *i)
{
607
	struct dlm_comm *cm = config_item_to_comm(i);
608 609
	if (local_comm == cm)
		local_comm = NULL;
610
	dlm_lowcomms_close(cm->nodeid);
611 612 613 614 615 616 617
	while (cm->addr_count--)
		kfree(cm->addr[cm->addr_count]);
	config_item_put(i);
}

static void release_comm(struct config_item *i)
{
618
	struct dlm_comm *cm = config_item_to_comm(i);
619 620 621
	kfree(cm);
}

622
static 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);
D
David Teigland 已提交
625
	struct dlm_node *nd;
626

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

	config_item_init_type_name(&nd->item, name, &node_type);
	nd->nodeid = -1;
	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 638
	list_add(&nd->list, &sp->members);
	sp->members_count++;
639
	mutex_unlock(&sp->members_lock);
640

641
	return &nd->item;
642 643 644 645
}

static void drop_node(struct config_group *g, struct config_item *i)
{
646 647
	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
	struct dlm_node *nd = config_item_to_node(i);
648

649
	mutex_lock(&sp->members_lock);
650 651
	list_del(&nd->list);
	sp->members_count--;
652
	mutex_unlock(&sp->members_lock);
653 654 655 656 657 658

	config_item_put(i);
}

static void release_node(struct config_item *i)
{
659
	struct dlm_node *nd = config_item_to_node(i);
660 661 662
	kfree(nd);
}

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

674
int __init dlm_config_init(void)
675 676
{
	config_group_init(&clusters_root.subsys.su_group);
677
	mutex_init(&clusters_root.subsys.su_mutex);
678 679 680 681 682 683 684 685 686 687 688 689
	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
 */

690 691 692
static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
			    char *buf)
{
693
	struct dlm_cluster *cl = config_item_to_cluster(i);
694 695 696 697 698 699 700 701 702
	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)
{
703
	struct dlm_cluster *cl = config_item_to_cluster(i);
704 705 706 707 708
	struct cluster_attribute *cla =
		container_of(a, struct cluster_attribute, attr);
	return cla->store ? cla->store(cl, buf, len) : -EINVAL;
}

709 710 711
static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
			 char *buf)
{
712
	struct dlm_comm *cm = config_item_to_comm(i);
713 714 715 716 717 718 719 720
	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)
{
721
	struct dlm_comm *cm = config_item_to_comm(i);
722 723 724 725 726
	struct comm_attribute *cma =
		container_of(a, struct comm_attribute, attr);
	return cma->store ? cma->store(cm, buf, len) : -EINVAL;
}

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

D
David Teigland 已提交
732 733
static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
				 size_t len)
734
{
735 736 737 738
	int rc = kstrtoint(buf, 0, &cm->nodeid);

	if (rc)
		return rc;
739 740 741
	return len;
}

D
David Teigland 已提交
742
static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
743 744 745 746
{
	return sprintf(buf, "%d\n", cm->local);
}

D
David Teigland 已提交
747 748
static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
				size_t len)
749
{
750 751 752 753
	int rc = kstrtoint(buf, 0, &cm->local);

	if (rc)
		return rc;
754 755 756 757 758
	if (cm->local && !local_comm)
		local_comm = cm;
	return len;
}

D
David Teigland 已提交
759
static 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 765 766 767 768 769

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

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

D
David Teigland 已提交
770
	addr = kzalloc(sizeof(*addr), GFP_NOFS);
771 772 773 774
	if (!addr)
		return -ENOMEM;

	memcpy(addr, buf, len);
775 776 777 778 779 780 781

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

782 783 784 785
	cm->addr[cm->addr_count++] = addr;
	return len;
}

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 821 822 823 824 825 826 827 828 829
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;
}

830 831 832
static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
			 char *buf)
{
833
	struct dlm_node *nd = config_item_to_node(i);
834 835 836 837 838 839 840 841
	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)
{
842
	struct dlm_node *nd = config_item_to_node(i);
843 844 845 846 847
	struct node_attribute *nda =
		container_of(a, struct node_attribute, attr);
	return nda->store ? nda->store(nd, buf, len) : -EINVAL;
}

D
David Teigland 已提交
848
static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
849 850 851 852
{
	return sprintf(buf, "%d\n", nd->nodeid);
}

D
David Teigland 已提交
853 854
static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
				 size_t len)
855
{
856
	uint32_t seq = 0;
857 858 859 860
	int rc = kstrtoint(buf, 0, &nd->nodeid);

	if (rc)
		return rc;
861 862
	dlm_comm_seq(nd->nodeid, &seq);
	nd->comm_seq = seq;
863 864 865
	return len;
}

D
David Teigland 已提交
866
static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
867 868 869 870
{
	return sprintf(buf, "%d\n", nd->weight);
}

D
David Teigland 已提交
871 872
static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
				 size_t len)
873
{
874 875 876 877
	int rc = kstrtoint(buf, 0, &nd->weight);

	if (rc)
		return rc;
878 879 880 881 882 883 884
	return len;
}

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

D
David Teigland 已提交
885
static struct dlm_space *get_space(char *name)
886
{
887 888
	struct config_item *i;

889 890
	if (!space_list)
		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
}

D
David Teigland 已提交
899
static void put_space(struct dlm_space *sp)
900 901 902 903
{
	config_item_put(&sp->group.cg_item);
}

904
static struct dlm_comm *get_comm(int nodeid)
905 906
{
	struct config_item *i;
D
David Teigland 已提交
907
	struct dlm_comm *cm = NULL;
908 909 910 911 912
	int found = 0;

	if (!comm_list)
		return NULL;

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 919 920 921 922
		if (cm->nodeid != nodeid)
			continue;
		found = 1;
		config_item_get(i);
		break;
923
	}
924
	mutex_unlock(&clusters_root.subsys.su_mutex);
925

926
	if (!found)
927 928 929 930
		cm = NULL;
	return cm;
}

D
David Teigland 已提交
931
static void put_comm(struct dlm_comm *cm)
932 933 934 935 936
{
	config_item_put(&cm->item);
}

/* caller must free mem */
937 938
int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
		     int *count_out)
939
{
D
David Teigland 已提交
940 941
	struct dlm_space *sp;
	struct dlm_node *nd;
942 943
	struct dlm_config_node *nodes, *node;
	int rv, count;
944 945 946 947 948

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

949
	mutex_lock(&sp->members_lock);
950
	if (!sp->members_count) {
951 952
		rv = -EINVAL;
		printk(KERN_ERR "dlm: zero members_count\n");
953 954 955
		goto out;
	}

956
	count = sp->members_count;
957

958 959
	nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
	if (!nodes) {
960 961 962 963
		rv = -ENOMEM;
		goto out;
	}

964
	node = nodes;
965
	list_for_each_entry(nd, &sp->members, list) {
966 967 968 969 970
		node->nodeid = nd->nodeid;
		node->weight = nd->weight;
		node->new = nd->new;
		node->comm_seq = nd->comm_seq;
		node++;
971

972
		nd->new = 0;
973
	}
974

975 976 977
	*count_out = count;
	*nodes_out = nodes;
	rv = 0;
978
 out:
979
	mutex_unlock(&sp->members_lock);
980 981 982 983
	put_space(sp);
	return rv;
}

984
int dlm_comm_seq(int nodeid, uint32_t *seq)
985
{
986
	struct dlm_comm *cm = get_comm(nodeid);
987 988 989 990 991
	if (!cm)
		return -EEXIST;
	*seq = cm->seq;
	put_comm(cm);
	return 0;
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
}

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
1013
#define DEFAULT_RSBTBL_SIZE     1024
1014 1015 1016
#define DEFAULT_RECOVER_TIMER      5
#define DEFAULT_TOSS_SECS         10
#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 1023
#define DEFAULT_RECOVER_CALLBACKS  0
#define DEFAULT_CLUSTER_NAME      ""
1024 1025

struct dlm_config_info dlm_config = {
1026 1027 1028 1029 1030
	.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,
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 1037 1038
	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
	.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
	.ci_cluster_name = DEFAULT_CLUSTER_NAME
1039 1040
};
新手
引导
客服 返回
顶部