162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2004, 2005 Oracle. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/slab.h> 762306a36Sopenharmony_ci#include <linux/kernel.h> 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/configfs.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "tcp.h" 1262306a36Sopenharmony_ci#include "nodemanager.h" 1362306a36Sopenharmony_ci#include "heartbeat.h" 1462306a36Sopenharmony_ci#include "masklog.h" 1562306a36Sopenharmony_ci#include "sys.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* for now we operate under the assertion that there can be only one 1862306a36Sopenharmony_ci * cluster active at a time. Changing this will require trickling 1962306a36Sopenharmony_ci * cluster references throughout where nodes are looked up */ 2062306a36Sopenharmony_cistruct o2nm_cluster *o2nm_single_cluster = NULL; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic const char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = { 2362306a36Sopenharmony_ci "reset", /* O2NM_FENCE_RESET */ 2462306a36Sopenharmony_ci "panic", /* O2NM_FENCE_PANIC */ 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic inline void o2nm_lock_subsystem(void); 2862306a36Sopenharmony_cistatic inline void o2nm_unlock_subsystem(void); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct o2nm_node *o2nm_get_node_by_num(u8 node_num) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct o2nm_node *node = NULL; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL) 3562306a36Sopenharmony_ci goto out; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci read_lock(&o2nm_single_cluster->cl_nodes_lock); 3862306a36Sopenharmony_ci node = o2nm_single_cluster->cl_nodes[node_num]; 3962306a36Sopenharmony_ci if (node) 4062306a36Sopenharmony_ci config_item_get(&node->nd_item); 4162306a36Sopenharmony_ci read_unlock(&o2nm_single_cluster->cl_nodes_lock); 4262306a36Sopenharmony_ciout: 4362306a36Sopenharmony_ci return node; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(o2nm_get_node_by_num); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciint o2nm_configured_node_map(unsigned long *map, unsigned bytes) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct o2nm_cluster *cluster = o2nm_single_cluster; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap))); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (cluster == NULL) 5462306a36Sopenharmony_ci return -EINVAL; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci read_lock(&cluster->cl_nodes_lock); 5762306a36Sopenharmony_ci bitmap_copy(map, cluster->cl_nodes_bitmap, O2NM_MAX_NODES); 5862306a36Sopenharmony_ci read_unlock(&cluster->cl_nodes_lock); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(o2nm_configured_node_map); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster, 6562306a36Sopenharmony_ci __be32 ip_needle, 6662306a36Sopenharmony_ci struct rb_node ***ret_p, 6762306a36Sopenharmony_ci struct rb_node **ret_parent) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct rb_node **p = &cluster->cl_node_ip_tree.rb_node; 7062306a36Sopenharmony_ci struct rb_node *parent = NULL; 7162306a36Sopenharmony_ci struct o2nm_node *node, *ret = NULL; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci while (*p) { 7462306a36Sopenharmony_ci int cmp; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci parent = *p; 7762306a36Sopenharmony_ci node = rb_entry(parent, struct o2nm_node, nd_ip_node); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci cmp = memcmp(&ip_needle, &node->nd_ipv4_address, 8062306a36Sopenharmony_ci sizeof(ip_needle)); 8162306a36Sopenharmony_ci if (cmp < 0) 8262306a36Sopenharmony_ci p = &(*p)->rb_left; 8362306a36Sopenharmony_ci else if (cmp > 0) 8462306a36Sopenharmony_ci p = &(*p)->rb_right; 8562306a36Sopenharmony_ci else { 8662306a36Sopenharmony_ci ret = node; 8762306a36Sopenharmony_ci break; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (ret_p != NULL) 9262306a36Sopenharmony_ci *ret_p = p; 9362306a36Sopenharmony_ci if (ret_parent != NULL) 9462306a36Sopenharmony_ci *ret_parent = parent; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return ret; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct o2nm_node *o2nm_get_node_by_ip(__be32 addr) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci struct o2nm_node *node = NULL; 10262306a36Sopenharmony_ci struct o2nm_cluster *cluster = o2nm_single_cluster; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (cluster == NULL) 10562306a36Sopenharmony_ci goto out; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci read_lock(&cluster->cl_nodes_lock); 10862306a36Sopenharmony_ci node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL); 10962306a36Sopenharmony_ci if (node) 11062306a36Sopenharmony_ci config_item_get(&node->nd_item); 11162306a36Sopenharmony_ci read_unlock(&cluster->cl_nodes_lock); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ciout: 11462306a36Sopenharmony_ci return node; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(o2nm_get_node_by_ip); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_civoid o2nm_node_put(struct o2nm_node *node) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci config_item_put(&node->nd_item); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(o2nm_node_put); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_civoid o2nm_node_get(struct o2nm_node *node) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci config_item_get(&node->nd_item); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(o2nm_node_get); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciu8 o2nm_this_node(void) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci u8 node_num = O2NM_MAX_NODES; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local) 13562306a36Sopenharmony_ci node_num = o2nm_single_cluster->cl_local_node; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci return node_num; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(o2nm_this_node); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* node configfs bits */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic struct o2nm_cluster *to_o2nm_cluster(struct config_item *item) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci return item ? 14662306a36Sopenharmony_ci container_of(to_config_group(item), struct o2nm_cluster, 14762306a36Sopenharmony_ci cl_group) 14862306a36Sopenharmony_ci : NULL; 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic struct o2nm_node *to_o2nm_node(struct config_item *item) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci return item ? container_of(item, struct o2nm_node, nd_item) : NULL; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic void o2nm_node_release(struct config_item *item) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct o2nm_node *node = to_o2nm_node(item); 15962306a36Sopenharmony_ci kfree(node); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic ssize_t o2nm_node_num_show(struct config_item *item, char *page) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci return sprintf(page, "%d\n", to_o2nm_node(item)->nd_num); 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci /* through the first node_set .parent 17062306a36Sopenharmony_ci * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ 17162306a36Sopenharmony_ci if (node->nd_item.ci_parent) 17262306a36Sopenharmony_ci return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); 17362306a36Sopenharmony_ci else 17462306a36Sopenharmony_ci return NULL; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cienum { 17862306a36Sopenharmony_ci O2NM_NODE_ATTR_NUM = 0, 17962306a36Sopenharmony_ci O2NM_NODE_ATTR_PORT, 18062306a36Sopenharmony_ci O2NM_NODE_ATTR_ADDRESS, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic ssize_t o2nm_node_num_store(struct config_item *item, const char *page, 18462306a36Sopenharmony_ci size_t count) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct o2nm_node *node = to_o2nm_node(item); 18762306a36Sopenharmony_ci struct o2nm_cluster *cluster; 18862306a36Sopenharmony_ci unsigned long tmp; 18962306a36Sopenharmony_ci char *p = (char *)page; 19062306a36Sopenharmony_ci int ret = 0; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci tmp = simple_strtoul(p, &p, 0); 19362306a36Sopenharmony_ci if (!p || (*p && (*p != '\n'))) 19462306a36Sopenharmony_ci return -EINVAL; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (tmp >= O2NM_MAX_NODES) 19762306a36Sopenharmony_ci return -ERANGE; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* once we're in the cl_nodes tree networking can look us up by 20062306a36Sopenharmony_ci * node number and try to use our address and port attributes 20162306a36Sopenharmony_ci * to connect to this node.. make sure that they've been set 20262306a36Sopenharmony_ci * before writing the node attribute? */ 20362306a36Sopenharmony_ci if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || 20462306a36Sopenharmony_ci !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) 20562306a36Sopenharmony_ci return -EINVAL; /* XXX */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci o2nm_lock_subsystem(); 20862306a36Sopenharmony_ci cluster = to_o2nm_cluster_from_node(node); 20962306a36Sopenharmony_ci if (!cluster) { 21062306a36Sopenharmony_ci o2nm_unlock_subsystem(); 21162306a36Sopenharmony_ci return -EINVAL; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci write_lock(&cluster->cl_nodes_lock); 21562306a36Sopenharmony_ci if (cluster->cl_nodes[tmp]) 21662306a36Sopenharmony_ci ret = -EEXIST; 21762306a36Sopenharmony_ci else if (test_and_set_bit(O2NM_NODE_ATTR_NUM, 21862306a36Sopenharmony_ci &node->nd_set_attributes)) 21962306a36Sopenharmony_ci ret = -EBUSY; 22062306a36Sopenharmony_ci else { 22162306a36Sopenharmony_ci cluster->cl_nodes[tmp] = node; 22262306a36Sopenharmony_ci node->nd_num = tmp; 22362306a36Sopenharmony_ci set_bit(tmp, cluster->cl_nodes_bitmap); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci write_unlock(&cluster->cl_nodes_lock); 22662306a36Sopenharmony_ci o2nm_unlock_subsystem(); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (ret) 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return count; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_cistatic ssize_t o2nm_node_ipv4_port_show(struct config_item *item, char *page) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci return sprintf(page, "%u\n", ntohs(to_o2nm_node(item)->nd_ipv4_port)); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic ssize_t o2nm_node_ipv4_port_store(struct config_item *item, 23962306a36Sopenharmony_ci const char *page, size_t count) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct o2nm_node *node = to_o2nm_node(item); 24262306a36Sopenharmony_ci unsigned long tmp; 24362306a36Sopenharmony_ci char *p = (char *)page; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci tmp = simple_strtoul(p, &p, 0); 24662306a36Sopenharmony_ci if (!p || (*p && (*p != '\n'))) 24762306a36Sopenharmony_ci return -EINVAL; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (tmp == 0) 25062306a36Sopenharmony_ci return -EINVAL; 25162306a36Sopenharmony_ci if (tmp >= (u16)-1) 25262306a36Sopenharmony_ci return -ERANGE; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (test_and_set_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) 25562306a36Sopenharmony_ci return -EBUSY; 25662306a36Sopenharmony_ci node->nd_ipv4_port = htons(tmp); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return count; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic ssize_t o2nm_node_ipv4_address_show(struct config_item *item, char *page) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci return sprintf(page, "%pI4\n", &to_o2nm_node(item)->nd_ipv4_address); 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic ssize_t o2nm_node_ipv4_address_store(struct config_item *item, 26762306a36Sopenharmony_ci const char *page, 26862306a36Sopenharmony_ci size_t count) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci struct o2nm_node *node = to_o2nm_node(item); 27162306a36Sopenharmony_ci struct o2nm_cluster *cluster; 27262306a36Sopenharmony_ci int ret, i; 27362306a36Sopenharmony_ci struct rb_node **p, *parent; 27462306a36Sopenharmony_ci unsigned int octets[4]; 27562306a36Sopenharmony_ci __be32 ipv4_addr = 0; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2], 27862306a36Sopenharmony_ci &octets[1], &octets[0]); 27962306a36Sopenharmony_ci if (ret != 4) 28062306a36Sopenharmony_ci return -EINVAL; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(octets); i++) { 28362306a36Sopenharmony_ci if (octets[i] > 255) 28462306a36Sopenharmony_ci return -ERANGE; 28562306a36Sopenharmony_ci be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci o2nm_lock_subsystem(); 28962306a36Sopenharmony_ci cluster = to_o2nm_cluster_from_node(node); 29062306a36Sopenharmony_ci if (!cluster) { 29162306a36Sopenharmony_ci o2nm_unlock_subsystem(); 29262306a36Sopenharmony_ci return -EINVAL; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci ret = 0; 29662306a36Sopenharmony_ci write_lock(&cluster->cl_nodes_lock); 29762306a36Sopenharmony_ci if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) 29862306a36Sopenharmony_ci ret = -EEXIST; 29962306a36Sopenharmony_ci else if (test_and_set_bit(O2NM_NODE_ATTR_ADDRESS, 30062306a36Sopenharmony_ci &node->nd_set_attributes)) 30162306a36Sopenharmony_ci ret = -EBUSY; 30262306a36Sopenharmony_ci else { 30362306a36Sopenharmony_ci rb_link_node(&node->nd_ip_node, parent, p); 30462306a36Sopenharmony_ci rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci write_unlock(&cluster->cl_nodes_lock); 30762306a36Sopenharmony_ci o2nm_unlock_subsystem(); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (ret) 31062306a36Sopenharmony_ci return ret; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr)); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci return count; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic ssize_t o2nm_node_local_show(struct config_item *item, char *page) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci return sprintf(page, "%d\n", to_o2nm_node(item)->nd_local); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic ssize_t o2nm_node_local_store(struct config_item *item, const char *page, 32362306a36Sopenharmony_ci size_t count) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct o2nm_node *node = to_o2nm_node(item); 32662306a36Sopenharmony_ci struct o2nm_cluster *cluster; 32762306a36Sopenharmony_ci unsigned long tmp; 32862306a36Sopenharmony_ci char *p = (char *)page; 32962306a36Sopenharmony_ci ssize_t ret; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci tmp = simple_strtoul(p, &p, 0); 33262306a36Sopenharmony_ci if (!p || (*p && (*p != '\n'))) 33362306a36Sopenharmony_ci return -EINVAL; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci tmp = !!tmp; /* boolean of whether this node wants to be local */ 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* setting local turns on networking rx for now so we require having 33862306a36Sopenharmony_ci * set everything else first */ 33962306a36Sopenharmony_ci if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || 34062306a36Sopenharmony_ci !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) || 34162306a36Sopenharmony_ci !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) 34262306a36Sopenharmony_ci return -EINVAL; /* XXX */ 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci o2nm_lock_subsystem(); 34562306a36Sopenharmony_ci cluster = to_o2nm_cluster_from_node(node); 34662306a36Sopenharmony_ci if (!cluster) { 34762306a36Sopenharmony_ci ret = -EINVAL; 34862306a36Sopenharmony_ci goto out; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* the only failure case is trying to set a new local node 35262306a36Sopenharmony_ci * when a different one is already set */ 35362306a36Sopenharmony_ci if (tmp && tmp == cluster->cl_has_local && 35462306a36Sopenharmony_ci cluster->cl_local_node != node->nd_num) { 35562306a36Sopenharmony_ci ret = -EBUSY; 35662306a36Sopenharmony_ci goto out; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci /* bring up the rx thread if we're setting the new local node. */ 36062306a36Sopenharmony_ci if (tmp && !cluster->cl_has_local) { 36162306a36Sopenharmony_ci ret = o2net_start_listening(node); 36262306a36Sopenharmony_ci if (ret) 36362306a36Sopenharmony_ci goto out; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if (!tmp && cluster->cl_has_local && 36762306a36Sopenharmony_ci cluster->cl_local_node == node->nd_num) { 36862306a36Sopenharmony_ci o2net_stop_listening(node); 36962306a36Sopenharmony_ci cluster->cl_local_node = O2NM_INVALID_NODE_NUM; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci node->nd_local = tmp; 37362306a36Sopenharmony_ci if (node->nd_local) { 37462306a36Sopenharmony_ci cluster->cl_has_local = tmp; 37562306a36Sopenharmony_ci cluster->cl_local_node = node->nd_num; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci ret = count; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ciout: 38162306a36Sopenharmony_ci o2nm_unlock_subsystem(); 38262306a36Sopenharmony_ci return ret; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_node_, num); 38662306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_node_, ipv4_port); 38762306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_node_, ipv4_address); 38862306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_node_, local); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic struct configfs_attribute *o2nm_node_attrs[] = { 39162306a36Sopenharmony_ci &o2nm_node_attr_num, 39262306a36Sopenharmony_ci &o2nm_node_attr_ipv4_port, 39362306a36Sopenharmony_ci &o2nm_node_attr_ipv4_address, 39462306a36Sopenharmony_ci &o2nm_node_attr_local, 39562306a36Sopenharmony_ci NULL, 39662306a36Sopenharmony_ci}; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic struct configfs_item_operations o2nm_node_item_ops = { 39962306a36Sopenharmony_ci .release = o2nm_node_release, 40062306a36Sopenharmony_ci}; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic const struct config_item_type o2nm_node_type = { 40362306a36Sopenharmony_ci .ct_item_ops = &o2nm_node_item_ops, 40462306a36Sopenharmony_ci .ct_attrs = o2nm_node_attrs, 40562306a36Sopenharmony_ci .ct_owner = THIS_MODULE, 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci/* node set */ 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistruct o2nm_node_group { 41162306a36Sopenharmony_ci struct config_group ns_group; 41262306a36Sopenharmony_ci /* some stuff? */ 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci#if 0 41662306a36Sopenharmony_cistatic struct o2nm_node_group *to_o2nm_node_group(struct config_group *group) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci return group ? 41962306a36Sopenharmony_ci container_of(group, struct o2nm_node_group, ns_group) 42062306a36Sopenharmony_ci : NULL; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci#endif 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count, 42562306a36Sopenharmony_ci unsigned int *val) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci unsigned long tmp; 42862306a36Sopenharmony_ci char *p = (char *)page; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci tmp = simple_strtoul(p, &p, 0); 43162306a36Sopenharmony_ci if (!p || (*p && (*p != '\n'))) 43262306a36Sopenharmony_ci return -EINVAL; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (tmp == 0) 43562306a36Sopenharmony_ci return -EINVAL; 43662306a36Sopenharmony_ci if (tmp >= (u32)-1) 43762306a36Sopenharmony_ci return -ERANGE; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci *val = tmp; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci return count; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic ssize_t o2nm_cluster_idle_timeout_ms_show(struct config_item *item, 44562306a36Sopenharmony_ci char *page) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci return sprintf(page, "%u\n", to_o2nm_cluster(item)->cl_idle_timeout_ms); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic ssize_t o2nm_cluster_idle_timeout_ms_store(struct config_item *item, 45162306a36Sopenharmony_ci const char *page, size_t count) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci struct o2nm_cluster *cluster = to_o2nm_cluster(item); 45462306a36Sopenharmony_ci ssize_t ret; 45562306a36Sopenharmony_ci unsigned int val; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ret = o2nm_cluster_attr_write(page, count, &val); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (ret > 0) { 46062306a36Sopenharmony_ci if (cluster->cl_idle_timeout_ms != val 46162306a36Sopenharmony_ci && o2net_num_connected_peers()) { 46262306a36Sopenharmony_ci mlog(ML_NOTICE, 46362306a36Sopenharmony_ci "o2net: cannot change idle timeout after " 46462306a36Sopenharmony_ci "the first peer has agreed to it." 46562306a36Sopenharmony_ci " %d connected peers\n", 46662306a36Sopenharmony_ci o2net_num_connected_peers()); 46762306a36Sopenharmony_ci ret = -EINVAL; 46862306a36Sopenharmony_ci } else if (val <= cluster->cl_keepalive_delay_ms) { 46962306a36Sopenharmony_ci mlog(ML_NOTICE, "o2net: idle timeout must be larger " 47062306a36Sopenharmony_ci "than keepalive delay\n"); 47162306a36Sopenharmony_ci ret = -EINVAL; 47262306a36Sopenharmony_ci } else { 47362306a36Sopenharmony_ci cluster->cl_idle_timeout_ms = val; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci return ret; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic ssize_t o2nm_cluster_keepalive_delay_ms_show( 48162306a36Sopenharmony_ci struct config_item *item, char *page) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci return sprintf(page, "%u\n", 48462306a36Sopenharmony_ci to_o2nm_cluster(item)->cl_keepalive_delay_ms); 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic ssize_t o2nm_cluster_keepalive_delay_ms_store( 48862306a36Sopenharmony_ci struct config_item *item, const char *page, size_t count) 48962306a36Sopenharmony_ci{ 49062306a36Sopenharmony_ci struct o2nm_cluster *cluster = to_o2nm_cluster(item); 49162306a36Sopenharmony_ci ssize_t ret; 49262306a36Sopenharmony_ci unsigned int val; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci ret = o2nm_cluster_attr_write(page, count, &val); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci if (ret > 0) { 49762306a36Sopenharmony_ci if (cluster->cl_keepalive_delay_ms != val 49862306a36Sopenharmony_ci && o2net_num_connected_peers()) { 49962306a36Sopenharmony_ci mlog(ML_NOTICE, 50062306a36Sopenharmony_ci "o2net: cannot change keepalive delay after" 50162306a36Sopenharmony_ci " the first peer has agreed to it." 50262306a36Sopenharmony_ci " %d connected peers\n", 50362306a36Sopenharmony_ci o2net_num_connected_peers()); 50462306a36Sopenharmony_ci ret = -EINVAL; 50562306a36Sopenharmony_ci } else if (val >= cluster->cl_idle_timeout_ms) { 50662306a36Sopenharmony_ci mlog(ML_NOTICE, "o2net: keepalive delay must be " 50762306a36Sopenharmony_ci "smaller than idle timeout\n"); 50862306a36Sopenharmony_ci ret = -EINVAL; 50962306a36Sopenharmony_ci } else { 51062306a36Sopenharmony_ci cluster->cl_keepalive_delay_ms = val; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return ret; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic ssize_t o2nm_cluster_reconnect_delay_ms_show( 51862306a36Sopenharmony_ci struct config_item *item, char *page) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci return sprintf(page, "%u\n", 52162306a36Sopenharmony_ci to_o2nm_cluster(item)->cl_reconnect_delay_ms); 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_cistatic ssize_t o2nm_cluster_reconnect_delay_ms_store( 52562306a36Sopenharmony_ci struct config_item *item, const char *page, size_t count) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci return o2nm_cluster_attr_write(page, count, 52862306a36Sopenharmony_ci &to_o2nm_cluster(item)->cl_reconnect_delay_ms); 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic ssize_t o2nm_cluster_fence_method_show( 53262306a36Sopenharmony_ci struct config_item *item, char *page) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci struct o2nm_cluster *cluster = to_o2nm_cluster(item); 53562306a36Sopenharmony_ci ssize_t ret = 0; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (cluster) 53862306a36Sopenharmony_ci ret = sprintf(page, "%s\n", 53962306a36Sopenharmony_ci o2nm_fence_method_desc[cluster->cl_fence_method]); 54062306a36Sopenharmony_ci return ret; 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic ssize_t o2nm_cluster_fence_method_store( 54462306a36Sopenharmony_ci struct config_item *item, const char *page, size_t count) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci unsigned int i; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci if (page[count - 1] != '\n') 54962306a36Sopenharmony_ci goto bail; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci for (i = 0; i < O2NM_FENCE_METHODS; ++i) { 55262306a36Sopenharmony_ci if (count != strlen(o2nm_fence_method_desc[i]) + 1) 55362306a36Sopenharmony_ci continue; 55462306a36Sopenharmony_ci if (strncasecmp(page, o2nm_fence_method_desc[i], count - 1)) 55562306a36Sopenharmony_ci continue; 55662306a36Sopenharmony_ci if (to_o2nm_cluster(item)->cl_fence_method != i) { 55762306a36Sopenharmony_ci printk(KERN_INFO "ocfs2: Changing fence method to %s\n", 55862306a36Sopenharmony_ci o2nm_fence_method_desc[i]); 55962306a36Sopenharmony_ci to_o2nm_cluster(item)->cl_fence_method = i; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci return count; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cibail: 56562306a36Sopenharmony_ci return -EINVAL; 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_cluster_, idle_timeout_ms); 56962306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_cluster_, keepalive_delay_ms); 57062306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_cluster_, reconnect_delay_ms); 57162306a36Sopenharmony_ciCONFIGFS_ATTR(o2nm_cluster_, fence_method); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistatic struct configfs_attribute *o2nm_cluster_attrs[] = { 57462306a36Sopenharmony_ci &o2nm_cluster_attr_idle_timeout_ms, 57562306a36Sopenharmony_ci &o2nm_cluster_attr_keepalive_delay_ms, 57662306a36Sopenharmony_ci &o2nm_cluster_attr_reconnect_delay_ms, 57762306a36Sopenharmony_ci &o2nm_cluster_attr_fence_method, 57862306a36Sopenharmony_ci NULL, 57962306a36Sopenharmony_ci}; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic struct config_item *o2nm_node_group_make_item(struct config_group *group, 58262306a36Sopenharmony_ci const char *name) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci struct o2nm_node *node = NULL; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (strlen(name) > O2NM_MAX_NAME_LEN) 58762306a36Sopenharmony_ci return ERR_PTR(-ENAMETOOLONG); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); 59062306a36Sopenharmony_ci if (node == NULL) 59162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ 59462306a36Sopenharmony_ci config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); 59562306a36Sopenharmony_ci spin_lock_init(&node->nd_lock); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci mlog(ML_CLUSTER, "o2nm: Registering node %s\n", name); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci return &node->nd_item; 60062306a36Sopenharmony_ci} 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_cistatic void o2nm_node_group_drop_item(struct config_group *group, 60362306a36Sopenharmony_ci struct config_item *item) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct o2nm_node *node = to_o2nm_node(item); 60662306a36Sopenharmony_ci struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci if (cluster->cl_nodes[node->nd_num] == node) { 60962306a36Sopenharmony_ci o2net_disconnect_node(node); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci if (cluster->cl_has_local && 61262306a36Sopenharmony_ci (cluster->cl_local_node == node->nd_num)) { 61362306a36Sopenharmony_ci cluster->cl_has_local = 0; 61462306a36Sopenharmony_ci cluster->cl_local_node = O2NM_INVALID_NODE_NUM; 61562306a36Sopenharmony_ci o2net_stop_listening(node); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* XXX call into net to stop this node from trading messages */ 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci write_lock(&cluster->cl_nodes_lock); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* XXX sloppy */ 62462306a36Sopenharmony_ci if (node->nd_ipv4_address) 62562306a36Sopenharmony_ci rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* nd_num might be 0 if the node number hasn't been set.. */ 62862306a36Sopenharmony_ci if (cluster->cl_nodes[node->nd_num] == node) { 62962306a36Sopenharmony_ci cluster->cl_nodes[node->nd_num] = NULL; 63062306a36Sopenharmony_ci clear_bit(node->nd_num, cluster->cl_nodes_bitmap); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci write_unlock(&cluster->cl_nodes_lock); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci mlog(ML_CLUSTER, "o2nm: Unregistered node %s\n", 63562306a36Sopenharmony_ci config_item_name(&node->nd_item)); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci config_item_put(item); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic struct configfs_group_operations o2nm_node_group_group_ops = { 64162306a36Sopenharmony_ci .make_item = o2nm_node_group_make_item, 64262306a36Sopenharmony_ci .drop_item = o2nm_node_group_drop_item, 64362306a36Sopenharmony_ci}; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic const struct config_item_type o2nm_node_group_type = { 64662306a36Sopenharmony_ci .ct_group_ops = &o2nm_node_group_group_ops, 64762306a36Sopenharmony_ci .ct_owner = THIS_MODULE, 64862306a36Sopenharmony_ci}; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci/* cluster */ 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic void o2nm_cluster_release(struct config_item *item) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci struct o2nm_cluster *cluster = to_o2nm_cluster(item); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci kfree(cluster); 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic struct configfs_item_operations o2nm_cluster_item_ops = { 66062306a36Sopenharmony_ci .release = o2nm_cluster_release, 66162306a36Sopenharmony_ci}; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic const struct config_item_type o2nm_cluster_type = { 66462306a36Sopenharmony_ci .ct_item_ops = &o2nm_cluster_item_ops, 66562306a36Sopenharmony_ci .ct_attrs = o2nm_cluster_attrs, 66662306a36Sopenharmony_ci .ct_owner = THIS_MODULE, 66762306a36Sopenharmony_ci}; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci/* cluster set */ 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistruct o2nm_cluster_group { 67262306a36Sopenharmony_ci struct configfs_subsystem cs_subsys; 67362306a36Sopenharmony_ci /* some stuff? */ 67462306a36Sopenharmony_ci}; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci#if 0 67762306a36Sopenharmony_cistatic struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci return group ? 68062306a36Sopenharmony_ci container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys) 68162306a36Sopenharmony_ci : NULL; 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci#endif 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistatic struct config_group *o2nm_cluster_group_make_group(struct config_group *group, 68662306a36Sopenharmony_ci const char *name) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct o2nm_cluster *cluster = NULL; 68962306a36Sopenharmony_ci struct o2nm_node_group *ns = NULL; 69062306a36Sopenharmony_ci struct config_group *o2hb_group = NULL, *ret = NULL; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci /* this runs under the parent dir's i_rwsem; there can be only 69362306a36Sopenharmony_ci * one caller in here at a time */ 69462306a36Sopenharmony_ci if (o2nm_single_cluster) 69562306a36Sopenharmony_ci return ERR_PTR(-ENOSPC); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); 69862306a36Sopenharmony_ci ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); 69962306a36Sopenharmony_ci o2hb_group = o2hb_alloc_hb_set(); 70062306a36Sopenharmony_ci if (cluster == NULL || ns == NULL || o2hb_group == NULL) 70162306a36Sopenharmony_ci goto out; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci config_group_init_type_name(&cluster->cl_group, name, 70462306a36Sopenharmony_ci &o2nm_cluster_type); 70562306a36Sopenharmony_ci configfs_add_default_group(&ns->ns_group, &cluster->cl_group); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci config_group_init_type_name(&ns->ns_group, "node", 70862306a36Sopenharmony_ci &o2nm_node_group_type); 70962306a36Sopenharmony_ci configfs_add_default_group(o2hb_group, &cluster->cl_group); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci rwlock_init(&cluster->cl_nodes_lock); 71262306a36Sopenharmony_ci cluster->cl_node_ip_tree = RB_ROOT; 71362306a36Sopenharmony_ci cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT; 71462306a36Sopenharmony_ci cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT; 71562306a36Sopenharmony_ci cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT; 71662306a36Sopenharmony_ci cluster->cl_fence_method = O2NM_FENCE_RESET; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci ret = &cluster->cl_group; 71962306a36Sopenharmony_ci o2nm_single_cluster = cluster; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ciout: 72262306a36Sopenharmony_ci if (ret == NULL) { 72362306a36Sopenharmony_ci kfree(cluster); 72462306a36Sopenharmony_ci kfree(ns); 72562306a36Sopenharmony_ci o2hb_free_hb_set(o2hb_group); 72662306a36Sopenharmony_ci ret = ERR_PTR(-ENOMEM); 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci return ret; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_cistatic void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci struct o2nm_cluster *cluster = to_o2nm_cluster(item); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci BUG_ON(o2nm_single_cluster != cluster); 73762306a36Sopenharmony_ci o2nm_single_cluster = NULL; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci configfs_remove_default_groups(&cluster->cl_group); 74062306a36Sopenharmony_ci config_item_put(item); 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic struct configfs_group_operations o2nm_cluster_group_group_ops = { 74462306a36Sopenharmony_ci .make_group = o2nm_cluster_group_make_group, 74562306a36Sopenharmony_ci .drop_item = o2nm_cluster_group_drop_item, 74662306a36Sopenharmony_ci}; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_cistatic const struct config_item_type o2nm_cluster_group_type = { 74962306a36Sopenharmony_ci .ct_group_ops = &o2nm_cluster_group_group_ops, 75062306a36Sopenharmony_ci .ct_owner = THIS_MODULE, 75162306a36Sopenharmony_ci}; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_cistatic struct o2nm_cluster_group o2nm_cluster_group = { 75462306a36Sopenharmony_ci .cs_subsys = { 75562306a36Sopenharmony_ci .su_group = { 75662306a36Sopenharmony_ci .cg_item = { 75762306a36Sopenharmony_ci .ci_namebuf = "cluster", 75862306a36Sopenharmony_ci .ci_type = &o2nm_cluster_group_type, 75962306a36Sopenharmony_ci }, 76062306a36Sopenharmony_ci }, 76162306a36Sopenharmony_ci }, 76262306a36Sopenharmony_ci}; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_cistatic inline void o2nm_lock_subsystem(void) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex); 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_cistatic inline void o2nm_unlock_subsystem(void) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex); 77262306a36Sopenharmony_ci} 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ciint o2nm_depend_item(struct config_item *item) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); 77762306a36Sopenharmony_ci} 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_civoid o2nm_undepend_item(struct config_item *item) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci configfs_undepend_item(item); 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ciint o2nm_depend_this_node(void) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci int ret = 0; 78762306a36Sopenharmony_ci struct o2nm_node *local_node; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci local_node = o2nm_get_node_by_num(o2nm_this_node()); 79062306a36Sopenharmony_ci if (!local_node) { 79162306a36Sopenharmony_ci ret = -EINVAL; 79262306a36Sopenharmony_ci goto out; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci ret = o2nm_depend_item(&local_node->nd_item); 79662306a36Sopenharmony_ci o2nm_node_put(local_node); 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ciout: 79962306a36Sopenharmony_ci return ret; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_civoid o2nm_undepend_this_node(void) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci struct o2nm_node *local_node; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci local_node = o2nm_get_node_by_num(o2nm_this_node()); 80762306a36Sopenharmony_ci BUG_ON(!local_node); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci o2nm_undepend_item(&local_node->nd_item); 81062306a36Sopenharmony_ci o2nm_node_put(local_node); 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic void __exit exit_o2nm(void) 81562306a36Sopenharmony_ci{ 81662306a36Sopenharmony_ci /* XXX sync with hb callbacks and shut down hb? */ 81762306a36Sopenharmony_ci o2net_unregister_hb_callbacks(); 81862306a36Sopenharmony_ci configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); 81962306a36Sopenharmony_ci o2cb_sys_shutdown(); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci o2net_exit(); 82262306a36Sopenharmony_ci o2hb_exit(); 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_cistatic int __init init_o2nm(void) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci int ret; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci o2hb_init(); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci ret = o2net_init(); 83262306a36Sopenharmony_ci if (ret) 83362306a36Sopenharmony_ci goto out_o2hb; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci ret = o2net_register_hb_callbacks(); 83662306a36Sopenharmony_ci if (ret) 83762306a36Sopenharmony_ci goto out_o2net; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci config_group_init(&o2nm_cluster_group.cs_subsys.su_group); 84062306a36Sopenharmony_ci mutex_init(&o2nm_cluster_group.cs_subsys.su_mutex); 84162306a36Sopenharmony_ci ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys); 84262306a36Sopenharmony_ci if (ret) { 84362306a36Sopenharmony_ci printk(KERN_ERR "nodemanager: Registration returned %d\n", ret); 84462306a36Sopenharmony_ci goto out_callbacks; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci ret = o2cb_sys_init(); 84862306a36Sopenharmony_ci if (!ret) 84962306a36Sopenharmony_ci goto out; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); 85262306a36Sopenharmony_ciout_callbacks: 85362306a36Sopenharmony_ci o2net_unregister_hb_callbacks(); 85462306a36Sopenharmony_ciout_o2net: 85562306a36Sopenharmony_ci o2net_exit(); 85662306a36Sopenharmony_ciout_o2hb: 85762306a36Sopenharmony_ci o2hb_exit(); 85862306a36Sopenharmony_ciout: 85962306a36Sopenharmony_ci return ret; 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ciMODULE_AUTHOR("Oracle"); 86362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 86462306a36Sopenharmony_ciMODULE_DESCRIPTION("OCFS2 cluster management"); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_cimodule_init(init_o2nm) 86762306a36Sopenharmony_cimodule_exit(exit_o2nm) 868