18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/******************************************************************************
38c2ecf20Sopenharmony_ci*******************************************************************************
48c2ecf20Sopenharmony_ci**
58c2ecf20Sopenharmony_ci**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
68c2ecf20Sopenharmony_ci**  Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
78c2ecf20Sopenharmony_ci**
88c2ecf20Sopenharmony_ci**
98c2ecf20Sopenharmony_ci*******************************************************************************
108c2ecf20Sopenharmony_ci******************************************************************************/
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/configfs.h>
158c2ecf20Sopenharmony_ci#include <linux/slab.h>
168c2ecf20Sopenharmony_ci#include <linux/in.h>
178c2ecf20Sopenharmony_ci#include <linux/in6.h>
188c2ecf20Sopenharmony_ci#include <linux/dlmconstants.h>
198c2ecf20Sopenharmony_ci#include <net/ipv6.h>
208c2ecf20Sopenharmony_ci#include <net/sock.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "config.h"
238c2ecf20Sopenharmony_ci#include "lowcomms.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid
278c2ecf20Sopenharmony_ci * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
288c2ecf20Sopenharmony_ci * /config/dlm/<cluster>/comms/<comm>/nodeid
298c2ecf20Sopenharmony_ci * /config/dlm/<cluster>/comms/<comm>/local
308c2ecf20Sopenharmony_ci * /config/dlm/<cluster>/comms/<comm>/addr      (write only)
318c2ecf20Sopenharmony_ci * /config/dlm/<cluster>/comms/<comm>/addr_list (read only)
328c2ecf20Sopenharmony_ci * The <cluster> level is useless, but I haven't figured out how to avoid it.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic struct config_group *space_list;
368c2ecf20Sopenharmony_cistatic struct config_group *comm_list;
378c2ecf20Sopenharmony_cistatic struct dlm_comm *local_comm;
388c2ecf20Sopenharmony_cistatic uint32_t dlm_comm_count;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistruct dlm_clusters;
418c2ecf20Sopenharmony_cistruct dlm_cluster;
428c2ecf20Sopenharmony_cistruct dlm_spaces;
438c2ecf20Sopenharmony_cistruct dlm_space;
448c2ecf20Sopenharmony_cistruct dlm_comms;
458c2ecf20Sopenharmony_cistruct dlm_comm;
468c2ecf20Sopenharmony_cistruct dlm_nodes;
478c2ecf20Sopenharmony_cistruct dlm_node;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic struct config_group *make_cluster(struct config_group *, const char *);
508c2ecf20Sopenharmony_cistatic void drop_cluster(struct config_group *, struct config_item *);
518c2ecf20Sopenharmony_cistatic void release_cluster(struct config_item *);
528c2ecf20Sopenharmony_cistatic struct config_group *make_space(struct config_group *, const char *);
538c2ecf20Sopenharmony_cistatic void drop_space(struct config_group *, struct config_item *);
548c2ecf20Sopenharmony_cistatic void release_space(struct config_item *);
558c2ecf20Sopenharmony_cistatic struct config_item *make_comm(struct config_group *, const char *);
568c2ecf20Sopenharmony_cistatic void drop_comm(struct config_group *, struct config_item *);
578c2ecf20Sopenharmony_cistatic void release_comm(struct config_item *);
588c2ecf20Sopenharmony_cistatic struct config_item *make_node(struct config_group *, const char *);
598c2ecf20Sopenharmony_cistatic void drop_node(struct config_group *, struct config_item *);
608c2ecf20Sopenharmony_cistatic void release_node(struct config_item *);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic struct configfs_attribute *comm_attrs[];
638c2ecf20Sopenharmony_cistatic struct configfs_attribute *node_attrs[];
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct dlm_cluster {
668c2ecf20Sopenharmony_ci	struct config_group group;
678c2ecf20Sopenharmony_ci	unsigned int cl_tcp_port;
688c2ecf20Sopenharmony_ci	unsigned int cl_buffer_size;
698c2ecf20Sopenharmony_ci	unsigned int cl_rsbtbl_size;
708c2ecf20Sopenharmony_ci	unsigned int cl_recover_timer;
718c2ecf20Sopenharmony_ci	unsigned int cl_toss_secs;
728c2ecf20Sopenharmony_ci	unsigned int cl_scan_secs;
738c2ecf20Sopenharmony_ci	unsigned int cl_log_debug;
748c2ecf20Sopenharmony_ci	unsigned int cl_log_info;
758c2ecf20Sopenharmony_ci	unsigned int cl_protocol;
768c2ecf20Sopenharmony_ci	unsigned int cl_mark;
778c2ecf20Sopenharmony_ci	unsigned int cl_timewarn_cs;
788c2ecf20Sopenharmony_ci	unsigned int cl_waitwarn_us;
798c2ecf20Sopenharmony_ci	unsigned int cl_new_rsb_count;
808c2ecf20Sopenharmony_ci	unsigned int cl_recover_callbacks;
818c2ecf20Sopenharmony_ci	char cl_cluster_name[DLM_LOCKSPACE_LEN];
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	struct dlm_spaces *sps;
848c2ecf20Sopenharmony_ci	struct dlm_comms *cms;
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic struct dlm_cluster *config_item_to_cluster(struct config_item *i)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
908c2ecf20Sopenharmony_ci		   NULL;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cienum {
948c2ecf20Sopenharmony_ci	CLUSTER_ATTR_TCP_PORT = 0,
958c2ecf20Sopenharmony_ci	CLUSTER_ATTR_BUFFER_SIZE,
968c2ecf20Sopenharmony_ci	CLUSTER_ATTR_RSBTBL_SIZE,
978c2ecf20Sopenharmony_ci	CLUSTER_ATTR_RECOVER_TIMER,
988c2ecf20Sopenharmony_ci	CLUSTER_ATTR_TOSS_SECS,
998c2ecf20Sopenharmony_ci	CLUSTER_ATTR_SCAN_SECS,
1008c2ecf20Sopenharmony_ci	CLUSTER_ATTR_LOG_DEBUG,
1018c2ecf20Sopenharmony_ci	CLUSTER_ATTR_LOG_INFO,
1028c2ecf20Sopenharmony_ci	CLUSTER_ATTR_PROTOCOL,
1038c2ecf20Sopenharmony_ci	CLUSTER_ATTR_MARK,
1048c2ecf20Sopenharmony_ci	CLUSTER_ATTR_TIMEWARN_CS,
1058c2ecf20Sopenharmony_ci	CLUSTER_ATTR_WAITWARN_US,
1068c2ecf20Sopenharmony_ci	CLUSTER_ATTR_NEW_RSB_COUNT,
1078c2ecf20Sopenharmony_ci	CLUSTER_ATTR_RECOVER_CALLBACKS,
1088c2ecf20Sopenharmony_ci	CLUSTER_ATTR_CLUSTER_NAME,
1098c2ecf20Sopenharmony_ci};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic ssize_t cluster_cluster_name_show(struct config_item *item, char *buf)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = config_item_to_cluster(item);
1148c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", cl->cl_cluster_name);
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic ssize_t cluster_cluster_name_store(struct config_item *item,
1188c2ecf20Sopenharmony_ci					  const char *buf, size_t len)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = config_item_to_cluster(item);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	strlcpy(dlm_config.ci_cluster_name, buf,
1238c2ecf20Sopenharmony_ci				sizeof(dlm_config.ci_cluster_name));
1248c2ecf20Sopenharmony_ci	strlcpy(cl->cl_cluster_name, buf, sizeof(cl->cl_cluster_name));
1258c2ecf20Sopenharmony_ci	return len;
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ciCONFIGFS_ATTR(cluster_, cluster_name);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
1318c2ecf20Sopenharmony_ci			   int *info_field, int (*check_cb)(unsigned int x),
1328c2ecf20Sopenharmony_ci			   const char *buf, size_t len)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	unsigned int x;
1358c2ecf20Sopenharmony_ci	int rc;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	if (!capable(CAP_SYS_ADMIN))
1388c2ecf20Sopenharmony_ci		return -EPERM;
1398c2ecf20Sopenharmony_ci	rc = kstrtouint(buf, 0, &x);
1408c2ecf20Sopenharmony_ci	if (rc)
1418c2ecf20Sopenharmony_ci		return rc;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (check_cb) {
1448c2ecf20Sopenharmony_ci		rc = check_cb(x);
1458c2ecf20Sopenharmony_ci		if (rc)
1468c2ecf20Sopenharmony_ci			return rc;
1478c2ecf20Sopenharmony_ci	}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	*cl_field = x;
1508c2ecf20Sopenharmony_ci	*info_field = x;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return len;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci#define CLUSTER_ATTR(name, check_cb)                                          \
1568c2ecf20Sopenharmony_cistatic ssize_t cluster_##name##_store(struct config_item *item, \
1578c2ecf20Sopenharmony_ci		const char *buf, size_t len) \
1588c2ecf20Sopenharmony_ci{                                                                             \
1598c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = config_item_to_cluster(item);		      \
1608c2ecf20Sopenharmony_ci	return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
1618c2ecf20Sopenharmony_ci			   check_cb, buf, len);                               \
1628c2ecf20Sopenharmony_ci}                                                                             \
1638c2ecf20Sopenharmony_cistatic ssize_t cluster_##name##_show(struct config_item *item, char *buf)     \
1648c2ecf20Sopenharmony_ci{                                                                             \
1658c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = config_item_to_cluster(item);		      \
1668c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
1678c2ecf20Sopenharmony_ci}                                                                             \
1688c2ecf20Sopenharmony_ciCONFIGFS_ATTR(cluster_, name);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic int dlm_check_zero(unsigned int x)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	if (!x)
1738c2ecf20Sopenharmony_ci		return -EINVAL;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	return 0;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic int dlm_check_buffer_size(unsigned int x)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	if (x < DEFAULT_BUFFER_SIZE)
1818c2ecf20Sopenharmony_ci		return -EINVAL;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	return 0;
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ciCLUSTER_ATTR(tcp_port, dlm_check_zero);
1878c2ecf20Sopenharmony_ciCLUSTER_ATTR(buffer_size, dlm_check_buffer_size);
1888c2ecf20Sopenharmony_ciCLUSTER_ATTR(rsbtbl_size, dlm_check_zero);
1898c2ecf20Sopenharmony_ciCLUSTER_ATTR(recover_timer, dlm_check_zero);
1908c2ecf20Sopenharmony_ciCLUSTER_ATTR(toss_secs, dlm_check_zero);
1918c2ecf20Sopenharmony_ciCLUSTER_ATTR(scan_secs, dlm_check_zero);
1928c2ecf20Sopenharmony_ciCLUSTER_ATTR(log_debug, NULL);
1938c2ecf20Sopenharmony_ciCLUSTER_ATTR(log_info, NULL);
1948c2ecf20Sopenharmony_ciCLUSTER_ATTR(protocol, NULL);
1958c2ecf20Sopenharmony_ciCLUSTER_ATTR(mark, NULL);
1968c2ecf20Sopenharmony_ciCLUSTER_ATTR(timewarn_cs, dlm_check_zero);
1978c2ecf20Sopenharmony_ciCLUSTER_ATTR(waitwarn_us, NULL);
1988c2ecf20Sopenharmony_ciCLUSTER_ATTR(new_rsb_count, NULL);
1998c2ecf20Sopenharmony_ciCLUSTER_ATTR(recover_callbacks, NULL);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic struct configfs_attribute *cluster_attrs[] = {
2028c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port,
2038c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size,
2048c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size,
2058c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer,
2068c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs,
2078c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs,
2088c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug,
2098c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_LOG_INFO] = &cluster_attr_log_info,
2108c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol,
2118c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_MARK] = &cluster_attr_mark,
2128c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs,
2138c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us,
2148c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count,
2158c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks,
2168c2ecf20Sopenharmony_ci	[CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name,
2178c2ecf20Sopenharmony_ci	NULL,
2188c2ecf20Sopenharmony_ci};
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cienum {
2218c2ecf20Sopenharmony_ci	COMM_ATTR_NODEID = 0,
2228c2ecf20Sopenharmony_ci	COMM_ATTR_LOCAL,
2238c2ecf20Sopenharmony_ci	COMM_ATTR_ADDR,
2248c2ecf20Sopenharmony_ci	COMM_ATTR_ADDR_LIST,
2258c2ecf20Sopenharmony_ci	COMM_ATTR_MARK,
2268c2ecf20Sopenharmony_ci};
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cienum {
2298c2ecf20Sopenharmony_ci	NODE_ATTR_NODEID = 0,
2308c2ecf20Sopenharmony_ci	NODE_ATTR_WEIGHT,
2318c2ecf20Sopenharmony_ci};
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistruct dlm_clusters {
2348c2ecf20Sopenharmony_ci	struct configfs_subsystem subsys;
2358c2ecf20Sopenharmony_ci};
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cistruct dlm_spaces {
2388c2ecf20Sopenharmony_ci	struct config_group ss_group;
2398c2ecf20Sopenharmony_ci};
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistruct dlm_space {
2428c2ecf20Sopenharmony_ci	struct config_group group;
2438c2ecf20Sopenharmony_ci	struct list_head members;
2448c2ecf20Sopenharmony_ci	struct mutex members_lock;
2458c2ecf20Sopenharmony_ci	int members_count;
2468c2ecf20Sopenharmony_ci	struct dlm_nodes *nds;
2478c2ecf20Sopenharmony_ci};
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistruct dlm_comms {
2508c2ecf20Sopenharmony_ci	struct config_group cs_group;
2518c2ecf20Sopenharmony_ci};
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistruct dlm_comm {
2548c2ecf20Sopenharmony_ci	struct config_item item;
2558c2ecf20Sopenharmony_ci	int seq;
2568c2ecf20Sopenharmony_ci	int nodeid;
2578c2ecf20Sopenharmony_ci	int local;
2588c2ecf20Sopenharmony_ci	int addr_count;
2598c2ecf20Sopenharmony_ci	unsigned int mark;
2608c2ecf20Sopenharmony_ci	struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
2618c2ecf20Sopenharmony_ci};
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistruct dlm_nodes {
2648c2ecf20Sopenharmony_ci	struct config_group ns_group;
2658c2ecf20Sopenharmony_ci};
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistruct dlm_node {
2688c2ecf20Sopenharmony_ci	struct config_item item;
2698c2ecf20Sopenharmony_ci	struct list_head list; /* space->members */
2708c2ecf20Sopenharmony_ci	int nodeid;
2718c2ecf20Sopenharmony_ci	int weight;
2728c2ecf20Sopenharmony_ci	int new;
2738c2ecf20Sopenharmony_ci	int comm_seq; /* copy of cm->seq when nd->nodeid is set */
2748c2ecf20Sopenharmony_ci};
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cistatic struct configfs_group_operations clusters_ops = {
2778c2ecf20Sopenharmony_ci	.make_group = make_cluster,
2788c2ecf20Sopenharmony_ci	.drop_item = drop_cluster,
2798c2ecf20Sopenharmony_ci};
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_cistatic struct configfs_item_operations cluster_ops = {
2828c2ecf20Sopenharmony_ci	.release = release_cluster,
2838c2ecf20Sopenharmony_ci};
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic struct configfs_group_operations spaces_ops = {
2868c2ecf20Sopenharmony_ci	.make_group = make_space,
2878c2ecf20Sopenharmony_ci	.drop_item = drop_space,
2888c2ecf20Sopenharmony_ci};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic struct configfs_item_operations space_ops = {
2918c2ecf20Sopenharmony_ci	.release = release_space,
2928c2ecf20Sopenharmony_ci};
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic struct configfs_group_operations comms_ops = {
2958c2ecf20Sopenharmony_ci	.make_item = make_comm,
2968c2ecf20Sopenharmony_ci	.drop_item = drop_comm,
2978c2ecf20Sopenharmony_ci};
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic struct configfs_item_operations comm_ops = {
3008c2ecf20Sopenharmony_ci	.release = release_comm,
3018c2ecf20Sopenharmony_ci};
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic struct configfs_group_operations nodes_ops = {
3048c2ecf20Sopenharmony_ci	.make_item = make_node,
3058c2ecf20Sopenharmony_ci	.drop_item = drop_node,
3068c2ecf20Sopenharmony_ci};
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic struct configfs_item_operations node_ops = {
3098c2ecf20Sopenharmony_ci	.release = release_node,
3108c2ecf20Sopenharmony_ci};
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic const struct config_item_type clusters_type = {
3138c2ecf20Sopenharmony_ci	.ct_group_ops = &clusters_ops,
3148c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const struct config_item_type cluster_type = {
3188c2ecf20Sopenharmony_ci	.ct_item_ops = &cluster_ops,
3198c2ecf20Sopenharmony_ci	.ct_attrs = cluster_attrs,
3208c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3218c2ecf20Sopenharmony_ci};
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic const struct config_item_type spaces_type = {
3248c2ecf20Sopenharmony_ci	.ct_group_ops = &spaces_ops,
3258c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3268c2ecf20Sopenharmony_ci};
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic const struct config_item_type space_type = {
3298c2ecf20Sopenharmony_ci	.ct_item_ops = &space_ops,
3308c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3318c2ecf20Sopenharmony_ci};
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic const struct config_item_type comms_type = {
3348c2ecf20Sopenharmony_ci	.ct_group_ops = &comms_ops,
3358c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3368c2ecf20Sopenharmony_ci};
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic const struct config_item_type comm_type = {
3398c2ecf20Sopenharmony_ci	.ct_item_ops = &comm_ops,
3408c2ecf20Sopenharmony_ci	.ct_attrs = comm_attrs,
3418c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3428c2ecf20Sopenharmony_ci};
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistatic const struct config_item_type nodes_type = {
3458c2ecf20Sopenharmony_ci	.ct_group_ops = &nodes_ops,
3468c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3478c2ecf20Sopenharmony_ci};
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cistatic const struct config_item_type node_type = {
3508c2ecf20Sopenharmony_ci	.ct_item_ops = &node_ops,
3518c2ecf20Sopenharmony_ci	.ct_attrs = node_attrs,
3528c2ecf20Sopenharmony_ci	.ct_owner = THIS_MODULE,
3538c2ecf20Sopenharmony_ci};
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic struct dlm_space *config_item_to_space(struct config_item *i)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	return i ? container_of(to_config_group(i), struct dlm_space, group) :
3588c2ecf20Sopenharmony_ci		   NULL;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic struct dlm_comm *config_item_to_comm(struct config_item *i)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	return i ? container_of(i, struct dlm_comm, item) : NULL;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic struct dlm_node *config_item_to_node(struct config_item *i)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	return i ? container_of(i, struct dlm_node, item) : NULL;
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic struct config_group *make_cluster(struct config_group *g,
3728c2ecf20Sopenharmony_ci					 const char *name)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = NULL;
3758c2ecf20Sopenharmony_ci	struct dlm_spaces *sps = NULL;
3768c2ecf20Sopenharmony_ci	struct dlm_comms *cms = NULL;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
3798c2ecf20Sopenharmony_ci	sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
3808c2ecf20Sopenharmony_ci	cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (!cl || !sps || !cms)
3838c2ecf20Sopenharmony_ci		goto fail;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	cl->sps = sps;
3868c2ecf20Sopenharmony_ci	cl->cms = cms;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	config_group_init_type_name(&cl->group, name, &cluster_type);
3898c2ecf20Sopenharmony_ci	config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
3908c2ecf20Sopenharmony_ci	config_group_init_type_name(&cms->cs_group, "comms", &comms_type);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	configfs_add_default_group(&sps->ss_group, &cl->group);
3938c2ecf20Sopenharmony_ci	configfs_add_default_group(&cms->cs_group, &cl->group);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	cl->cl_tcp_port = dlm_config.ci_tcp_port;
3968c2ecf20Sopenharmony_ci	cl->cl_buffer_size = dlm_config.ci_buffer_size;
3978c2ecf20Sopenharmony_ci	cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size;
3988c2ecf20Sopenharmony_ci	cl->cl_recover_timer = dlm_config.ci_recover_timer;
3998c2ecf20Sopenharmony_ci	cl->cl_toss_secs = dlm_config.ci_toss_secs;
4008c2ecf20Sopenharmony_ci	cl->cl_scan_secs = dlm_config.ci_scan_secs;
4018c2ecf20Sopenharmony_ci	cl->cl_log_debug = dlm_config.ci_log_debug;
4028c2ecf20Sopenharmony_ci	cl->cl_log_info = dlm_config.ci_log_info;
4038c2ecf20Sopenharmony_ci	cl->cl_protocol = dlm_config.ci_protocol;
4048c2ecf20Sopenharmony_ci	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
4058c2ecf20Sopenharmony_ci	cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
4068c2ecf20Sopenharmony_ci	cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
4078c2ecf20Sopenharmony_ci	cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
4088c2ecf20Sopenharmony_ci	memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
4098c2ecf20Sopenharmony_ci	       DLM_LOCKSPACE_LEN);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	space_list = &sps->ss_group;
4128c2ecf20Sopenharmony_ci	comm_list = &cms->cs_group;
4138c2ecf20Sopenharmony_ci	return &cl->group;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci fail:
4168c2ecf20Sopenharmony_ci	kfree(cl);
4178c2ecf20Sopenharmony_ci	kfree(sps);
4188c2ecf20Sopenharmony_ci	kfree(cms);
4198c2ecf20Sopenharmony_ci	return ERR_PTR(-ENOMEM);
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cistatic void drop_cluster(struct config_group *g, struct config_item *i)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = config_item_to_cluster(i);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	configfs_remove_default_groups(&cl->group);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	space_list = NULL;
4298c2ecf20Sopenharmony_ci	comm_list = NULL;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	config_item_put(i);
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_cistatic void release_cluster(struct config_item *i)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	struct dlm_cluster *cl = config_item_to_cluster(i);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	kfree(cl->sps);
4398c2ecf20Sopenharmony_ci	kfree(cl->cms);
4408c2ecf20Sopenharmony_ci	kfree(cl);
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_cistatic struct config_group *make_space(struct config_group *g, const char *name)
4448c2ecf20Sopenharmony_ci{
4458c2ecf20Sopenharmony_ci	struct dlm_space *sp = NULL;
4468c2ecf20Sopenharmony_ci	struct dlm_nodes *nds = NULL;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
4498c2ecf20Sopenharmony_ci	nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (!sp || !nds)
4528c2ecf20Sopenharmony_ci		goto fail;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	config_group_init_type_name(&sp->group, name, &space_type);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type);
4578c2ecf20Sopenharmony_ci	configfs_add_default_group(&nds->ns_group, &sp->group);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&sp->members);
4608c2ecf20Sopenharmony_ci	mutex_init(&sp->members_lock);
4618c2ecf20Sopenharmony_ci	sp->members_count = 0;
4628c2ecf20Sopenharmony_ci	sp->nds = nds;
4638c2ecf20Sopenharmony_ci	return &sp->group;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci fail:
4668c2ecf20Sopenharmony_ci	kfree(sp);
4678c2ecf20Sopenharmony_ci	kfree(nds);
4688c2ecf20Sopenharmony_ci	return ERR_PTR(-ENOMEM);
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic void drop_space(struct config_group *g, struct config_item *i)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct dlm_space *sp = config_item_to_space(i);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* assert list_empty(&sp->members) */
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	configfs_remove_default_groups(&sp->group);
4788c2ecf20Sopenharmony_ci	config_item_put(i);
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic void release_space(struct config_item *i)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	struct dlm_space *sp = config_item_to_space(i);
4848c2ecf20Sopenharmony_ci	kfree(sp->nds);
4858c2ecf20Sopenharmony_ci	kfree(sp);
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cistatic struct config_item *make_comm(struct config_group *g, const char *name)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	struct dlm_comm *cm;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
4938c2ecf20Sopenharmony_ci	if (!cm)
4948c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	config_item_init_type_name(&cm->item, name, &comm_type);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	cm->seq = dlm_comm_count++;
4998c2ecf20Sopenharmony_ci	if (!cm->seq)
5008c2ecf20Sopenharmony_ci		cm->seq = dlm_comm_count++;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	cm->nodeid = -1;
5038c2ecf20Sopenharmony_ci	cm->local = 0;
5048c2ecf20Sopenharmony_ci	cm->addr_count = 0;
5058c2ecf20Sopenharmony_ci	cm->mark = 0;
5068c2ecf20Sopenharmony_ci	return &cm->item;
5078c2ecf20Sopenharmony_ci}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_cistatic void drop_comm(struct config_group *g, struct config_item *i)
5108c2ecf20Sopenharmony_ci{
5118c2ecf20Sopenharmony_ci	struct dlm_comm *cm = config_item_to_comm(i);
5128c2ecf20Sopenharmony_ci	if (local_comm == cm)
5138c2ecf20Sopenharmony_ci		local_comm = NULL;
5148c2ecf20Sopenharmony_ci	dlm_lowcomms_close(cm->nodeid);
5158c2ecf20Sopenharmony_ci	while (cm->addr_count--)
5168c2ecf20Sopenharmony_ci		kfree(cm->addr[cm->addr_count]);
5178c2ecf20Sopenharmony_ci	config_item_put(i);
5188c2ecf20Sopenharmony_ci}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cistatic void release_comm(struct config_item *i)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	struct dlm_comm *cm = config_item_to_comm(i);
5238c2ecf20Sopenharmony_ci	kfree(cm);
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_cistatic struct config_item *make_node(struct config_group *g, const char *name)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
5298c2ecf20Sopenharmony_ci	struct dlm_node *nd;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
5328c2ecf20Sopenharmony_ci	if (!nd)
5338c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	config_item_init_type_name(&nd->item, name, &node_type);
5368c2ecf20Sopenharmony_ci	nd->nodeid = -1;
5378c2ecf20Sopenharmony_ci	nd->weight = 1;  /* default weight of 1 if none is set */
5388c2ecf20Sopenharmony_ci	nd->new = 1;     /* set to 0 once it's been read by dlm_nodeid_list() */
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	mutex_lock(&sp->members_lock);
5418c2ecf20Sopenharmony_ci	list_add(&nd->list, &sp->members);
5428c2ecf20Sopenharmony_ci	sp->members_count++;
5438c2ecf20Sopenharmony_ci	mutex_unlock(&sp->members_lock);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	return &nd->item;
5468c2ecf20Sopenharmony_ci}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_cistatic void drop_node(struct config_group *g, struct config_item *i)
5498c2ecf20Sopenharmony_ci{
5508c2ecf20Sopenharmony_ci	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
5518c2ecf20Sopenharmony_ci	struct dlm_node *nd = config_item_to_node(i);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	mutex_lock(&sp->members_lock);
5548c2ecf20Sopenharmony_ci	list_del(&nd->list);
5558c2ecf20Sopenharmony_ci	sp->members_count--;
5568c2ecf20Sopenharmony_ci	mutex_unlock(&sp->members_lock);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	config_item_put(i);
5598c2ecf20Sopenharmony_ci}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_cistatic void release_node(struct config_item *i)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct dlm_node *nd = config_item_to_node(i);
5648c2ecf20Sopenharmony_ci	kfree(nd);
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic struct dlm_clusters clusters_root = {
5688c2ecf20Sopenharmony_ci	.subsys = {
5698c2ecf20Sopenharmony_ci		.su_group = {
5708c2ecf20Sopenharmony_ci			.cg_item = {
5718c2ecf20Sopenharmony_ci				.ci_namebuf = "dlm",
5728c2ecf20Sopenharmony_ci				.ci_type = &clusters_type,
5738c2ecf20Sopenharmony_ci			},
5748c2ecf20Sopenharmony_ci		},
5758c2ecf20Sopenharmony_ci	},
5768c2ecf20Sopenharmony_ci};
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ciint __init dlm_config_init(void)
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	config_group_init(&clusters_root.subsys.su_group);
5818c2ecf20Sopenharmony_ci	mutex_init(&clusters_root.subsys.su_mutex);
5828c2ecf20Sopenharmony_ci	return configfs_register_subsystem(&clusters_root.subsys);
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_civoid dlm_config_exit(void)
5868c2ecf20Sopenharmony_ci{
5878c2ecf20Sopenharmony_ci	configfs_unregister_subsystem(&clusters_root.subsys);
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci/*
5918c2ecf20Sopenharmony_ci * Functions for user space to read/write attributes
5928c2ecf20Sopenharmony_ci */
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic ssize_t comm_nodeid_show(struct config_item *item, char *buf)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", config_item_to_comm(item)->nodeid);
5978c2ecf20Sopenharmony_ci}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cistatic ssize_t comm_nodeid_store(struct config_item *item, const char *buf,
6008c2ecf20Sopenharmony_ci				 size_t len)
6018c2ecf20Sopenharmony_ci{
6028c2ecf20Sopenharmony_ci	int rc = kstrtoint(buf, 0, &config_item_to_comm(item)->nodeid);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (rc)
6058c2ecf20Sopenharmony_ci		return rc;
6068c2ecf20Sopenharmony_ci	return len;
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic ssize_t comm_local_show(struct config_item *item, char *buf)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", config_item_to_comm(item)->local);
6128c2ecf20Sopenharmony_ci}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic ssize_t comm_local_store(struct config_item *item, const char *buf,
6158c2ecf20Sopenharmony_ci				size_t len)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	struct dlm_comm *cm = config_item_to_comm(item);
6188c2ecf20Sopenharmony_ci	int rc = kstrtoint(buf, 0, &cm->local);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	if (rc)
6218c2ecf20Sopenharmony_ci		return rc;
6228c2ecf20Sopenharmony_ci	if (cm->local && !local_comm)
6238c2ecf20Sopenharmony_ci		local_comm = cm;
6248c2ecf20Sopenharmony_ci	return len;
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_cistatic ssize_t comm_addr_store(struct config_item *item, const char *buf,
6288c2ecf20Sopenharmony_ci		size_t len)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	struct dlm_comm *cm = config_item_to_comm(item);
6318c2ecf20Sopenharmony_ci	struct sockaddr_storage *addr;
6328c2ecf20Sopenharmony_ci	int rv;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	if (len != sizeof(struct sockaddr_storage))
6358c2ecf20Sopenharmony_ci		return -EINVAL;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	if (cm->addr_count >= DLM_MAX_ADDR_COUNT)
6388c2ecf20Sopenharmony_ci		return -ENOSPC;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	addr = kzalloc(sizeof(*addr), GFP_NOFS);
6418c2ecf20Sopenharmony_ci	if (!addr)
6428c2ecf20Sopenharmony_ci		return -ENOMEM;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	memcpy(addr, buf, len);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	rv = dlm_lowcomms_addr(cm->nodeid, addr, len);
6478c2ecf20Sopenharmony_ci	if (rv) {
6488c2ecf20Sopenharmony_ci		kfree(addr);
6498c2ecf20Sopenharmony_ci		return rv;
6508c2ecf20Sopenharmony_ci	}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	cm->addr[cm->addr_count++] = addr;
6538c2ecf20Sopenharmony_ci	return len;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic ssize_t comm_addr_list_show(struct config_item *item, char *buf)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	struct dlm_comm *cm = config_item_to_comm(item);
6598c2ecf20Sopenharmony_ci	ssize_t s;
6608c2ecf20Sopenharmony_ci	ssize_t allowance;
6618c2ecf20Sopenharmony_ci	int i;
6628c2ecf20Sopenharmony_ci	struct sockaddr_storage *addr;
6638c2ecf20Sopenharmony_ci	struct sockaddr_in *addr_in;
6648c2ecf20Sopenharmony_ci	struct sockaddr_in6 *addr_in6;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	/* Taken from ip6_addr_string() defined in lib/vsprintf.c */
6678c2ecf20Sopenharmony_ci	char buf0[sizeof("AF_INET6	xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255\n")];
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	/* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */
6718c2ecf20Sopenharmony_ci	allowance = 4096;
6728c2ecf20Sopenharmony_ci	buf[0] = '\0';
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	for (i = 0; i < cm->addr_count; i++) {
6758c2ecf20Sopenharmony_ci		addr = cm->addr[i];
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci		switch(addr->ss_family) {
6788c2ecf20Sopenharmony_ci		case AF_INET:
6798c2ecf20Sopenharmony_ci			addr_in = (struct sockaddr_in *)addr;
6808c2ecf20Sopenharmony_ci			s = sprintf(buf0, "AF_INET	%pI4\n", &addr_in->sin_addr.s_addr);
6818c2ecf20Sopenharmony_ci			break;
6828c2ecf20Sopenharmony_ci		case AF_INET6:
6838c2ecf20Sopenharmony_ci			addr_in6 = (struct sockaddr_in6 *)addr;
6848c2ecf20Sopenharmony_ci			s = sprintf(buf0, "AF_INET6	%pI6\n", &addr_in6->sin6_addr);
6858c2ecf20Sopenharmony_ci			break;
6868c2ecf20Sopenharmony_ci		default:
6878c2ecf20Sopenharmony_ci			s = sprintf(buf0, "%s\n", "<UNKNOWN>");
6888c2ecf20Sopenharmony_ci			break;
6898c2ecf20Sopenharmony_ci		}
6908c2ecf20Sopenharmony_ci		allowance -= s;
6918c2ecf20Sopenharmony_ci		if (allowance >= 0)
6928c2ecf20Sopenharmony_ci			strcat(buf, buf0);
6938c2ecf20Sopenharmony_ci		else {
6948c2ecf20Sopenharmony_ci			allowance += s;
6958c2ecf20Sopenharmony_ci			break;
6968c2ecf20Sopenharmony_ci		}
6978c2ecf20Sopenharmony_ci	}
6988c2ecf20Sopenharmony_ci	return 4096 - allowance;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cistatic ssize_t comm_mark_show(struct config_item *item, char *buf)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	return sprintf(buf, "%u\n", config_item_to_comm(item)->mark);
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_cistatic ssize_t comm_mark_store(struct config_item *item, const char *buf,
7078c2ecf20Sopenharmony_ci			       size_t len)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	unsigned int mark;
7108c2ecf20Sopenharmony_ci	int rc;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	rc = kstrtouint(buf, 0, &mark);
7138c2ecf20Sopenharmony_ci	if (rc)
7148c2ecf20Sopenharmony_ci		return rc;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	config_item_to_comm(item)->mark = mark;
7178c2ecf20Sopenharmony_ci	return len;
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ciCONFIGFS_ATTR(comm_, nodeid);
7218c2ecf20Sopenharmony_ciCONFIGFS_ATTR(comm_, local);
7228c2ecf20Sopenharmony_ciCONFIGFS_ATTR(comm_, mark);
7238c2ecf20Sopenharmony_ciCONFIGFS_ATTR_WO(comm_, addr);
7248c2ecf20Sopenharmony_ciCONFIGFS_ATTR_RO(comm_, addr_list);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic struct configfs_attribute *comm_attrs[] = {
7278c2ecf20Sopenharmony_ci	[COMM_ATTR_NODEID] = &comm_attr_nodeid,
7288c2ecf20Sopenharmony_ci	[COMM_ATTR_LOCAL] = &comm_attr_local,
7298c2ecf20Sopenharmony_ci	[COMM_ATTR_ADDR] = &comm_attr_addr,
7308c2ecf20Sopenharmony_ci	[COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list,
7318c2ecf20Sopenharmony_ci	[COMM_ATTR_MARK] = &comm_attr_mark,
7328c2ecf20Sopenharmony_ci	NULL,
7338c2ecf20Sopenharmony_ci};
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_cistatic ssize_t node_nodeid_show(struct config_item *item, char *buf)
7368c2ecf20Sopenharmony_ci{
7378c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", config_item_to_node(item)->nodeid);
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_cistatic ssize_t node_nodeid_store(struct config_item *item, const char *buf,
7418c2ecf20Sopenharmony_ci				 size_t len)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	struct dlm_node *nd = config_item_to_node(item);
7448c2ecf20Sopenharmony_ci	uint32_t seq = 0;
7458c2ecf20Sopenharmony_ci	int rc = kstrtoint(buf, 0, &nd->nodeid);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (rc)
7488c2ecf20Sopenharmony_ci		return rc;
7498c2ecf20Sopenharmony_ci	dlm_comm_seq(nd->nodeid, &seq);
7508c2ecf20Sopenharmony_ci	nd->comm_seq = seq;
7518c2ecf20Sopenharmony_ci	return len;
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistatic ssize_t node_weight_show(struct config_item *item, char *buf)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", config_item_to_node(item)->weight);
7578c2ecf20Sopenharmony_ci}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_cistatic ssize_t node_weight_store(struct config_item *item, const char *buf,
7608c2ecf20Sopenharmony_ci				 size_t len)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	int rc = kstrtoint(buf, 0, &config_item_to_node(item)->weight);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	if (rc)
7658c2ecf20Sopenharmony_ci		return rc;
7668c2ecf20Sopenharmony_ci	return len;
7678c2ecf20Sopenharmony_ci}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ciCONFIGFS_ATTR(node_, nodeid);
7708c2ecf20Sopenharmony_ciCONFIGFS_ATTR(node_, weight);
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cistatic struct configfs_attribute *node_attrs[] = {
7738c2ecf20Sopenharmony_ci	[NODE_ATTR_NODEID] = &node_attr_nodeid,
7748c2ecf20Sopenharmony_ci	[NODE_ATTR_WEIGHT] = &node_attr_weight,
7758c2ecf20Sopenharmony_ci	NULL,
7768c2ecf20Sopenharmony_ci};
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci/*
7798c2ecf20Sopenharmony_ci * Functions for the dlm to get the info that's been configured
7808c2ecf20Sopenharmony_ci */
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic struct dlm_space *get_space(char *name)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	struct config_item *i;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	if (!space_list)
7878c2ecf20Sopenharmony_ci		return NULL;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	mutex_lock(&space_list->cg_subsys->su_mutex);
7908c2ecf20Sopenharmony_ci	i = config_group_find_item(space_list, name);
7918c2ecf20Sopenharmony_ci	mutex_unlock(&space_list->cg_subsys->su_mutex);
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	return config_item_to_space(i);
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_cistatic void put_space(struct dlm_space *sp)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	config_item_put(&sp->group.cg_item);
7998c2ecf20Sopenharmony_ci}
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cistatic struct dlm_comm *get_comm(int nodeid)
8028c2ecf20Sopenharmony_ci{
8038c2ecf20Sopenharmony_ci	struct config_item *i;
8048c2ecf20Sopenharmony_ci	struct dlm_comm *cm = NULL;
8058c2ecf20Sopenharmony_ci	int found = 0;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	if (!comm_list)
8088c2ecf20Sopenharmony_ci		return NULL;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	mutex_lock(&clusters_root.subsys.su_mutex);
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
8138c2ecf20Sopenharmony_ci		cm = config_item_to_comm(i);
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci		if (cm->nodeid != nodeid)
8168c2ecf20Sopenharmony_ci			continue;
8178c2ecf20Sopenharmony_ci		found = 1;
8188c2ecf20Sopenharmony_ci		config_item_get(i);
8198c2ecf20Sopenharmony_ci		break;
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci	mutex_unlock(&clusters_root.subsys.su_mutex);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	if (!found)
8248c2ecf20Sopenharmony_ci		cm = NULL;
8258c2ecf20Sopenharmony_ci	return cm;
8268c2ecf20Sopenharmony_ci}
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_cistatic void put_comm(struct dlm_comm *cm)
8298c2ecf20Sopenharmony_ci{
8308c2ecf20Sopenharmony_ci	config_item_put(&cm->item);
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci/* caller must free mem */
8348c2ecf20Sopenharmony_ciint dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
8358c2ecf20Sopenharmony_ci		     int *count_out)
8368c2ecf20Sopenharmony_ci{
8378c2ecf20Sopenharmony_ci	struct dlm_space *sp;
8388c2ecf20Sopenharmony_ci	struct dlm_node *nd;
8398c2ecf20Sopenharmony_ci	struct dlm_config_node *nodes, *node;
8408c2ecf20Sopenharmony_ci	int rv, count;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	sp = get_space(lsname);
8438c2ecf20Sopenharmony_ci	if (!sp)
8448c2ecf20Sopenharmony_ci		return -EEXIST;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	mutex_lock(&sp->members_lock);
8478c2ecf20Sopenharmony_ci	if (!sp->members_count) {
8488c2ecf20Sopenharmony_ci		rv = -EINVAL;
8498c2ecf20Sopenharmony_ci		printk(KERN_ERR "dlm: zero members_count\n");
8508c2ecf20Sopenharmony_ci		goto out;
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	count = sp->members_count;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
8568c2ecf20Sopenharmony_ci	if (!nodes) {
8578c2ecf20Sopenharmony_ci		rv = -ENOMEM;
8588c2ecf20Sopenharmony_ci		goto out;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	node = nodes;
8628c2ecf20Sopenharmony_ci	list_for_each_entry(nd, &sp->members, list) {
8638c2ecf20Sopenharmony_ci		node->nodeid = nd->nodeid;
8648c2ecf20Sopenharmony_ci		node->weight = nd->weight;
8658c2ecf20Sopenharmony_ci		node->new = nd->new;
8668c2ecf20Sopenharmony_ci		node->comm_seq = nd->comm_seq;
8678c2ecf20Sopenharmony_ci		node++;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci		nd->new = 0;
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	*count_out = count;
8738c2ecf20Sopenharmony_ci	*nodes_out = nodes;
8748c2ecf20Sopenharmony_ci	rv = 0;
8758c2ecf20Sopenharmony_ci out:
8768c2ecf20Sopenharmony_ci	mutex_unlock(&sp->members_lock);
8778c2ecf20Sopenharmony_ci	put_space(sp);
8788c2ecf20Sopenharmony_ci	return rv;
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ciint dlm_comm_seq(int nodeid, uint32_t *seq)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	struct dlm_comm *cm = get_comm(nodeid);
8848c2ecf20Sopenharmony_ci	if (!cm)
8858c2ecf20Sopenharmony_ci		return -EEXIST;
8868c2ecf20Sopenharmony_ci	*seq = cm->seq;
8878c2ecf20Sopenharmony_ci	put_comm(cm);
8888c2ecf20Sopenharmony_ci	return 0;
8898c2ecf20Sopenharmony_ci}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_civoid dlm_comm_mark(int nodeid, unsigned int *mark)
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	struct dlm_comm *cm;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	cm = get_comm(nodeid);
8968c2ecf20Sopenharmony_ci	if (!cm) {
8978c2ecf20Sopenharmony_ci		*mark = dlm_config.ci_mark;
8988c2ecf20Sopenharmony_ci		return;
8998c2ecf20Sopenharmony_ci	}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	if (cm->mark)
9028c2ecf20Sopenharmony_ci		*mark = cm->mark;
9038c2ecf20Sopenharmony_ci	else
9048c2ecf20Sopenharmony_ci		*mark = dlm_config.ci_mark;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	put_comm(cm);
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ciint dlm_our_nodeid(void)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	return local_comm ? local_comm->nodeid : 0;
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci/* num 0 is first addr, num 1 is second addr */
9158c2ecf20Sopenharmony_ciint dlm_our_addr(struct sockaddr_storage *addr, int num)
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	if (!local_comm)
9188c2ecf20Sopenharmony_ci		return -1;
9198c2ecf20Sopenharmony_ci	if (num + 1 > local_comm->addr_count)
9208c2ecf20Sopenharmony_ci		return -1;
9218c2ecf20Sopenharmony_ci	memcpy(addr, local_comm->addr[num], sizeof(*addr));
9228c2ecf20Sopenharmony_ci	return 0;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci/* Config file defaults */
9268c2ecf20Sopenharmony_ci#define DEFAULT_TCP_PORT       21064
9278c2ecf20Sopenharmony_ci#define DEFAULT_RSBTBL_SIZE     1024
9288c2ecf20Sopenharmony_ci#define DEFAULT_RECOVER_TIMER      5
9298c2ecf20Sopenharmony_ci#define DEFAULT_TOSS_SECS         10
9308c2ecf20Sopenharmony_ci#define DEFAULT_SCAN_SECS          5
9318c2ecf20Sopenharmony_ci#define DEFAULT_LOG_DEBUG          0
9328c2ecf20Sopenharmony_ci#define DEFAULT_LOG_INFO           1
9338c2ecf20Sopenharmony_ci#define DEFAULT_PROTOCOL           0
9348c2ecf20Sopenharmony_ci#define DEFAULT_MARK               0
9358c2ecf20Sopenharmony_ci#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
9368c2ecf20Sopenharmony_ci#define DEFAULT_WAITWARN_US	   0
9378c2ecf20Sopenharmony_ci#define DEFAULT_NEW_RSB_COUNT    128
9388c2ecf20Sopenharmony_ci#define DEFAULT_RECOVER_CALLBACKS  0
9398c2ecf20Sopenharmony_ci#define DEFAULT_CLUSTER_NAME      ""
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_cistruct dlm_config_info dlm_config = {
9428c2ecf20Sopenharmony_ci	.ci_tcp_port = DEFAULT_TCP_PORT,
9438c2ecf20Sopenharmony_ci	.ci_buffer_size = DEFAULT_BUFFER_SIZE,
9448c2ecf20Sopenharmony_ci	.ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
9458c2ecf20Sopenharmony_ci	.ci_recover_timer = DEFAULT_RECOVER_TIMER,
9468c2ecf20Sopenharmony_ci	.ci_toss_secs = DEFAULT_TOSS_SECS,
9478c2ecf20Sopenharmony_ci	.ci_scan_secs = DEFAULT_SCAN_SECS,
9488c2ecf20Sopenharmony_ci	.ci_log_debug = DEFAULT_LOG_DEBUG,
9498c2ecf20Sopenharmony_ci	.ci_log_info = DEFAULT_LOG_INFO,
9508c2ecf20Sopenharmony_ci	.ci_protocol = DEFAULT_PROTOCOL,
9518c2ecf20Sopenharmony_ci	.ci_mark = DEFAULT_MARK,
9528c2ecf20Sopenharmony_ci	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
9538c2ecf20Sopenharmony_ci	.ci_waitwarn_us = DEFAULT_WAITWARN_US,
9548c2ecf20Sopenharmony_ci	.ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
9558c2ecf20Sopenharmony_ci	.ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
9568c2ecf20Sopenharmony_ci	.ci_cluster_name = DEFAULT_CLUSTER_NAME
9578c2ecf20Sopenharmony_ci};
9588c2ecf20Sopenharmony_ci
959