File Index
Files and directories
Sign in
FILE

config.c

File preview with syntax highlighting.

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