cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

config.c (23790B)


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