1*0c83ed8eSKurt Hackel /* -*- mode: c; c-basic-offset: 8; -*- 2*0c83ed8eSKurt Hackel * vim: noexpandtab sw=8 ts=8 sts=0: 3*0c83ed8eSKurt Hackel * 4*0c83ed8eSKurt Hackel * Copyright (C) 2004, 2005 Oracle. All rights reserved. 5*0c83ed8eSKurt Hackel * 6*0c83ed8eSKurt Hackel * This program is free software; you can redistribute it and/or 7*0c83ed8eSKurt Hackel * modify it under the terms of the GNU General Public 8*0c83ed8eSKurt Hackel * License as published by the Free Software Foundation; either 9*0c83ed8eSKurt Hackel * version 2 of the License, or (at your option) any later version. 10*0c83ed8eSKurt Hackel * 11*0c83ed8eSKurt Hackel * This program is distributed in the hope that it will be useful, 12*0c83ed8eSKurt Hackel * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*0c83ed8eSKurt Hackel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*0c83ed8eSKurt Hackel * General Public License for more details. 15*0c83ed8eSKurt Hackel * 16*0c83ed8eSKurt Hackel * You should have received a copy of the GNU General Public 17*0c83ed8eSKurt Hackel * License along with this program; if not, write to the 18*0c83ed8eSKurt Hackel * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19*0c83ed8eSKurt Hackel * Boston, MA 021110-1307, USA. 20*0c83ed8eSKurt Hackel */ 21*0c83ed8eSKurt Hackel 22*0c83ed8eSKurt Hackel #include <linux/kernel.h> 23*0c83ed8eSKurt Hackel #include <linux/module.h> 24*0c83ed8eSKurt Hackel #include <linux/sysctl.h> 25*0c83ed8eSKurt Hackel #include <linux/configfs.h> 26*0c83ed8eSKurt Hackel 27*0c83ed8eSKurt Hackel #include "endian.h" 28*0c83ed8eSKurt Hackel #include "tcp.h" 29*0c83ed8eSKurt Hackel #include "nodemanager.h" 30*0c83ed8eSKurt Hackel #include "heartbeat.h" 31*0c83ed8eSKurt Hackel #include "masklog.h" 32*0c83ed8eSKurt Hackel #include "sys.h" 33*0c83ed8eSKurt Hackel #include "ver.h" 34*0c83ed8eSKurt Hackel 35*0c83ed8eSKurt Hackel /* for now we operate under the assertion that there can be only one 36*0c83ed8eSKurt Hackel * cluster active at a time. Changing this will require trickling 37*0c83ed8eSKurt Hackel * cluster references throughout where nodes are looked up */ 38*0c83ed8eSKurt Hackel static struct o2nm_cluster *o2nm_single_cluster = NULL; 39*0c83ed8eSKurt Hackel 40*0c83ed8eSKurt Hackel #define OCFS2_MAX_HB_CTL_PATH 256 41*0c83ed8eSKurt Hackel static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl"; 42*0c83ed8eSKurt Hackel 43*0c83ed8eSKurt Hackel static ctl_table ocfs2_nm_table[] = { 44*0c83ed8eSKurt Hackel { 45*0c83ed8eSKurt Hackel .ctl_name = 1, 46*0c83ed8eSKurt Hackel .procname = "hb_ctl_path", 47*0c83ed8eSKurt Hackel .data = ocfs2_hb_ctl_path, 48*0c83ed8eSKurt Hackel .maxlen = OCFS2_MAX_HB_CTL_PATH, 49*0c83ed8eSKurt Hackel .mode = 0644, 50*0c83ed8eSKurt Hackel .proc_handler = &proc_dostring, 51*0c83ed8eSKurt Hackel .strategy = &sysctl_string, 52*0c83ed8eSKurt Hackel }, 53*0c83ed8eSKurt Hackel { .ctl_name = 0 } 54*0c83ed8eSKurt Hackel }; 55*0c83ed8eSKurt Hackel 56*0c83ed8eSKurt Hackel static ctl_table ocfs2_mod_table[] = { 57*0c83ed8eSKurt Hackel { 58*0c83ed8eSKurt Hackel .ctl_name = KERN_OCFS2_NM, 59*0c83ed8eSKurt Hackel .procname = "nm", 60*0c83ed8eSKurt Hackel .data = NULL, 61*0c83ed8eSKurt Hackel .maxlen = 0, 62*0c83ed8eSKurt Hackel .mode = 0555, 63*0c83ed8eSKurt Hackel .child = ocfs2_nm_table 64*0c83ed8eSKurt Hackel }, 65*0c83ed8eSKurt Hackel { .ctl_name = 0} 66*0c83ed8eSKurt Hackel }; 67*0c83ed8eSKurt Hackel 68*0c83ed8eSKurt Hackel static ctl_table ocfs2_kern_table[] = { 69*0c83ed8eSKurt Hackel { 70*0c83ed8eSKurt Hackel .ctl_name = KERN_OCFS2, 71*0c83ed8eSKurt Hackel .procname = "ocfs2", 72*0c83ed8eSKurt Hackel .data = NULL, 73*0c83ed8eSKurt Hackel .maxlen = 0, 74*0c83ed8eSKurt Hackel .mode = 0555, 75*0c83ed8eSKurt Hackel .child = ocfs2_mod_table 76*0c83ed8eSKurt Hackel }, 77*0c83ed8eSKurt Hackel { .ctl_name = 0} 78*0c83ed8eSKurt Hackel }; 79*0c83ed8eSKurt Hackel 80*0c83ed8eSKurt Hackel static ctl_table ocfs2_root_table[] = { 81*0c83ed8eSKurt Hackel { 82*0c83ed8eSKurt Hackel .ctl_name = CTL_FS, 83*0c83ed8eSKurt Hackel .procname = "fs", 84*0c83ed8eSKurt Hackel .data = NULL, 85*0c83ed8eSKurt Hackel .maxlen = 0, 86*0c83ed8eSKurt Hackel .mode = 0555, 87*0c83ed8eSKurt Hackel .child = ocfs2_kern_table 88*0c83ed8eSKurt Hackel }, 89*0c83ed8eSKurt Hackel { .ctl_name = 0 } 90*0c83ed8eSKurt Hackel }; 91*0c83ed8eSKurt Hackel 92*0c83ed8eSKurt Hackel static struct ctl_table_header *ocfs2_table_header = NULL; 93*0c83ed8eSKurt Hackel 94*0c83ed8eSKurt Hackel const char *o2nm_get_hb_ctl_path(void) 95*0c83ed8eSKurt Hackel { 96*0c83ed8eSKurt Hackel return ocfs2_hb_ctl_path; 97*0c83ed8eSKurt Hackel } 98*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_hb_ctl_path); 99*0c83ed8eSKurt Hackel 100*0c83ed8eSKurt Hackel struct o2nm_cluster { 101*0c83ed8eSKurt Hackel struct config_group cl_group; 102*0c83ed8eSKurt Hackel unsigned cl_has_local:1; 103*0c83ed8eSKurt Hackel u8 cl_local_node; 104*0c83ed8eSKurt Hackel rwlock_t cl_nodes_lock; 105*0c83ed8eSKurt Hackel struct o2nm_node *cl_nodes[O2NM_MAX_NODES]; 106*0c83ed8eSKurt Hackel struct rb_root cl_node_ip_tree; 107*0c83ed8eSKurt Hackel /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */ 108*0c83ed8eSKurt Hackel unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 109*0c83ed8eSKurt Hackel }; 110*0c83ed8eSKurt Hackel 111*0c83ed8eSKurt Hackel struct o2nm_node *o2nm_get_node_by_num(u8 node_num) 112*0c83ed8eSKurt Hackel { 113*0c83ed8eSKurt Hackel struct o2nm_node *node = NULL; 114*0c83ed8eSKurt Hackel 115*0c83ed8eSKurt Hackel if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL) 116*0c83ed8eSKurt Hackel goto out; 117*0c83ed8eSKurt Hackel 118*0c83ed8eSKurt Hackel read_lock(&o2nm_single_cluster->cl_nodes_lock); 119*0c83ed8eSKurt Hackel node = o2nm_single_cluster->cl_nodes[node_num]; 120*0c83ed8eSKurt Hackel if (node) 121*0c83ed8eSKurt Hackel config_item_get(&node->nd_item); 122*0c83ed8eSKurt Hackel read_unlock(&o2nm_single_cluster->cl_nodes_lock); 123*0c83ed8eSKurt Hackel out: 124*0c83ed8eSKurt Hackel return node; 125*0c83ed8eSKurt Hackel } 126*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_node_by_num); 127*0c83ed8eSKurt Hackel 128*0c83ed8eSKurt Hackel int o2nm_configured_node_map(unsigned long *map, unsigned bytes) 129*0c83ed8eSKurt Hackel { 130*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = o2nm_single_cluster; 131*0c83ed8eSKurt Hackel 132*0c83ed8eSKurt Hackel BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap))); 133*0c83ed8eSKurt Hackel 134*0c83ed8eSKurt Hackel if (cluster == NULL) 135*0c83ed8eSKurt Hackel return -EINVAL; 136*0c83ed8eSKurt Hackel 137*0c83ed8eSKurt Hackel read_lock(&cluster->cl_nodes_lock); 138*0c83ed8eSKurt Hackel memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap)); 139*0c83ed8eSKurt Hackel read_unlock(&cluster->cl_nodes_lock); 140*0c83ed8eSKurt Hackel 141*0c83ed8eSKurt Hackel return 0; 142*0c83ed8eSKurt Hackel } 143*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_configured_node_map); 144*0c83ed8eSKurt Hackel 145*0c83ed8eSKurt Hackel static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster, 146*0c83ed8eSKurt Hackel __be32 ip_needle, 147*0c83ed8eSKurt Hackel struct rb_node ***ret_p, 148*0c83ed8eSKurt Hackel struct rb_node **ret_parent) 149*0c83ed8eSKurt Hackel { 150*0c83ed8eSKurt Hackel struct rb_node **p = &cluster->cl_node_ip_tree.rb_node; 151*0c83ed8eSKurt Hackel struct rb_node *parent = NULL; 152*0c83ed8eSKurt Hackel struct o2nm_node *node, *ret = NULL; 153*0c83ed8eSKurt Hackel 154*0c83ed8eSKurt Hackel while (*p) { 155*0c83ed8eSKurt Hackel parent = *p; 156*0c83ed8eSKurt Hackel node = rb_entry(parent, struct o2nm_node, nd_ip_node); 157*0c83ed8eSKurt Hackel 158*0c83ed8eSKurt Hackel if (memcmp(&ip_needle, &node->nd_ipv4_address, 159*0c83ed8eSKurt Hackel sizeof(ip_needle)) < 0) 160*0c83ed8eSKurt Hackel p = &(*p)->rb_left; 161*0c83ed8eSKurt Hackel else if (memcmp(&ip_needle, &node->nd_ipv4_address, 162*0c83ed8eSKurt Hackel sizeof(ip_needle)) > 0) 163*0c83ed8eSKurt Hackel p = &(*p)->rb_right; 164*0c83ed8eSKurt Hackel else { 165*0c83ed8eSKurt Hackel ret = node; 166*0c83ed8eSKurt Hackel break; 167*0c83ed8eSKurt Hackel } 168*0c83ed8eSKurt Hackel } 169*0c83ed8eSKurt Hackel 170*0c83ed8eSKurt Hackel if (ret_p != NULL) 171*0c83ed8eSKurt Hackel *ret_p = p; 172*0c83ed8eSKurt Hackel if (ret_parent != NULL) 173*0c83ed8eSKurt Hackel *ret_parent = parent; 174*0c83ed8eSKurt Hackel 175*0c83ed8eSKurt Hackel return ret; 176*0c83ed8eSKurt Hackel } 177*0c83ed8eSKurt Hackel 178*0c83ed8eSKurt Hackel struct o2nm_node *o2nm_get_node_by_ip(__be32 addr) 179*0c83ed8eSKurt Hackel { 180*0c83ed8eSKurt Hackel struct o2nm_node *node = NULL; 181*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = o2nm_single_cluster; 182*0c83ed8eSKurt Hackel 183*0c83ed8eSKurt Hackel if (cluster == NULL) 184*0c83ed8eSKurt Hackel goto out; 185*0c83ed8eSKurt Hackel 186*0c83ed8eSKurt Hackel read_lock(&cluster->cl_nodes_lock); 187*0c83ed8eSKurt Hackel node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL); 188*0c83ed8eSKurt Hackel if (node) 189*0c83ed8eSKurt Hackel config_item_get(&node->nd_item); 190*0c83ed8eSKurt Hackel read_unlock(&cluster->cl_nodes_lock); 191*0c83ed8eSKurt Hackel 192*0c83ed8eSKurt Hackel out: 193*0c83ed8eSKurt Hackel return node; 194*0c83ed8eSKurt Hackel } 195*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip); 196*0c83ed8eSKurt Hackel 197*0c83ed8eSKurt Hackel void o2nm_node_put(struct o2nm_node *node) 198*0c83ed8eSKurt Hackel { 199*0c83ed8eSKurt Hackel config_item_put(&node->nd_item); 200*0c83ed8eSKurt Hackel } 201*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_node_put); 202*0c83ed8eSKurt Hackel 203*0c83ed8eSKurt Hackel void o2nm_node_get(struct o2nm_node *node) 204*0c83ed8eSKurt Hackel { 205*0c83ed8eSKurt Hackel config_item_get(&node->nd_item); 206*0c83ed8eSKurt Hackel } 207*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_node_get); 208*0c83ed8eSKurt Hackel 209*0c83ed8eSKurt Hackel u8 o2nm_this_node(void) 210*0c83ed8eSKurt Hackel { 211*0c83ed8eSKurt Hackel u8 node_num = O2NM_MAX_NODES; 212*0c83ed8eSKurt Hackel 213*0c83ed8eSKurt Hackel if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local) 214*0c83ed8eSKurt Hackel node_num = o2nm_single_cluster->cl_local_node; 215*0c83ed8eSKurt Hackel 216*0c83ed8eSKurt Hackel return node_num; 217*0c83ed8eSKurt Hackel } 218*0c83ed8eSKurt Hackel EXPORT_SYMBOL_GPL(o2nm_this_node); 219*0c83ed8eSKurt Hackel 220*0c83ed8eSKurt Hackel /* node configfs bits */ 221*0c83ed8eSKurt Hackel 222*0c83ed8eSKurt Hackel static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item) 223*0c83ed8eSKurt Hackel { 224*0c83ed8eSKurt Hackel return item ? 225*0c83ed8eSKurt Hackel container_of(to_config_group(item), struct o2nm_cluster, 226*0c83ed8eSKurt Hackel cl_group) 227*0c83ed8eSKurt Hackel : NULL; 228*0c83ed8eSKurt Hackel } 229*0c83ed8eSKurt Hackel 230*0c83ed8eSKurt Hackel static struct o2nm_node *to_o2nm_node(struct config_item *item) 231*0c83ed8eSKurt Hackel { 232*0c83ed8eSKurt Hackel return item ? container_of(item, struct o2nm_node, nd_item) : NULL; 233*0c83ed8eSKurt Hackel } 234*0c83ed8eSKurt Hackel 235*0c83ed8eSKurt Hackel static void o2nm_node_release(struct config_item *item) 236*0c83ed8eSKurt Hackel { 237*0c83ed8eSKurt Hackel struct o2nm_node *node = to_o2nm_node(item); 238*0c83ed8eSKurt Hackel kfree(node); 239*0c83ed8eSKurt Hackel } 240*0c83ed8eSKurt Hackel 241*0c83ed8eSKurt Hackel static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page) 242*0c83ed8eSKurt Hackel { 243*0c83ed8eSKurt Hackel return sprintf(page, "%d\n", node->nd_num); 244*0c83ed8eSKurt Hackel } 245*0c83ed8eSKurt Hackel 246*0c83ed8eSKurt Hackel static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node) 247*0c83ed8eSKurt Hackel { 248*0c83ed8eSKurt Hackel /* through the first node_set .parent 249*0c83ed8eSKurt Hackel * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ 250*0c83ed8eSKurt Hackel return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); 251*0c83ed8eSKurt Hackel } 252*0c83ed8eSKurt Hackel 253*0c83ed8eSKurt Hackel enum { 254*0c83ed8eSKurt Hackel O2NM_NODE_ATTR_NUM = 0, 255*0c83ed8eSKurt Hackel O2NM_NODE_ATTR_PORT, 256*0c83ed8eSKurt Hackel O2NM_NODE_ATTR_ADDRESS, 257*0c83ed8eSKurt Hackel O2NM_NODE_ATTR_LOCAL, 258*0c83ed8eSKurt Hackel }; 259*0c83ed8eSKurt Hackel 260*0c83ed8eSKurt Hackel static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, 261*0c83ed8eSKurt Hackel size_t count) 262*0c83ed8eSKurt Hackel { 263*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); 264*0c83ed8eSKurt Hackel unsigned long tmp; 265*0c83ed8eSKurt Hackel char *p = (char *)page; 266*0c83ed8eSKurt Hackel 267*0c83ed8eSKurt Hackel tmp = simple_strtoul(p, &p, 0); 268*0c83ed8eSKurt Hackel if (!p || (*p && (*p != '\n'))) 269*0c83ed8eSKurt Hackel return -EINVAL; 270*0c83ed8eSKurt Hackel 271*0c83ed8eSKurt Hackel if (tmp >= O2NM_MAX_NODES) 272*0c83ed8eSKurt Hackel return -ERANGE; 273*0c83ed8eSKurt Hackel 274*0c83ed8eSKurt Hackel /* once we're in the cl_nodes tree networking can look us up by 275*0c83ed8eSKurt Hackel * node number and try to use our address and port attributes 276*0c83ed8eSKurt Hackel * to connect to this node.. make sure that they've been set 277*0c83ed8eSKurt Hackel * before writing the node attribute? */ 278*0c83ed8eSKurt Hackel if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || 279*0c83ed8eSKurt Hackel !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) 280*0c83ed8eSKurt Hackel return -EINVAL; /* XXX */ 281*0c83ed8eSKurt Hackel 282*0c83ed8eSKurt Hackel write_lock(&cluster->cl_nodes_lock); 283*0c83ed8eSKurt Hackel if (cluster->cl_nodes[tmp]) 284*0c83ed8eSKurt Hackel p = NULL; 285*0c83ed8eSKurt Hackel else { 286*0c83ed8eSKurt Hackel cluster->cl_nodes[tmp] = node; 287*0c83ed8eSKurt Hackel node->nd_num = tmp; 288*0c83ed8eSKurt Hackel set_bit(tmp, cluster->cl_nodes_bitmap); 289*0c83ed8eSKurt Hackel } 290*0c83ed8eSKurt Hackel write_unlock(&cluster->cl_nodes_lock); 291*0c83ed8eSKurt Hackel if (p == NULL) 292*0c83ed8eSKurt Hackel return -EEXIST; 293*0c83ed8eSKurt Hackel 294*0c83ed8eSKurt Hackel return count; 295*0c83ed8eSKurt Hackel } 296*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page) 297*0c83ed8eSKurt Hackel { 298*0c83ed8eSKurt Hackel return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port)); 299*0c83ed8eSKurt Hackel } 300*0c83ed8eSKurt Hackel 301*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node, 302*0c83ed8eSKurt Hackel const char *page, size_t count) 303*0c83ed8eSKurt Hackel { 304*0c83ed8eSKurt Hackel unsigned long tmp; 305*0c83ed8eSKurt Hackel char *p = (char *)page; 306*0c83ed8eSKurt Hackel 307*0c83ed8eSKurt Hackel tmp = simple_strtoul(p, &p, 0); 308*0c83ed8eSKurt Hackel if (!p || (*p && (*p != '\n'))) 309*0c83ed8eSKurt Hackel return -EINVAL; 310*0c83ed8eSKurt Hackel 311*0c83ed8eSKurt Hackel if (tmp == 0) 312*0c83ed8eSKurt Hackel return -EINVAL; 313*0c83ed8eSKurt Hackel if (tmp >= (u16)-1) 314*0c83ed8eSKurt Hackel return -ERANGE; 315*0c83ed8eSKurt Hackel 316*0c83ed8eSKurt Hackel node->nd_ipv4_port = htons(tmp); 317*0c83ed8eSKurt Hackel 318*0c83ed8eSKurt Hackel return count; 319*0c83ed8eSKurt Hackel } 320*0c83ed8eSKurt Hackel 321*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page) 322*0c83ed8eSKurt Hackel { 323*0c83ed8eSKurt Hackel return sprintf(page, "%u.%u.%u.%u\n", NIPQUAD(node->nd_ipv4_address)); 324*0c83ed8eSKurt Hackel } 325*0c83ed8eSKurt Hackel 326*0c83ed8eSKurt Hackel static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node, 327*0c83ed8eSKurt Hackel const char *page, 328*0c83ed8eSKurt Hackel size_t count) 329*0c83ed8eSKurt Hackel { 330*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); 331*0c83ed8eSKurt Hackel int ret, i; 332*0c83ed8eSKurt Hackel struct rb_node **p, *parent; 333*0c83ed8eSKurt Hackel unsigned int octets[4]; 334*0c83ed8eSKurt Hackel __be32 ipv4_addr = 0; 335*0c83ed8eSKurt Hackel 336*0c83ed8eSKurt Hackel ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2], 337*0c83ed8eSKurt Hackel &octets[1], &octets[0]); 338*0c83ed8eSKurt Hackel if (ret != 4) 339*0c83ed8eSKurt Hackel return -EINVAL; 340*0c83ed8eSKurt Hackel 341*0c83ed8eSKurt Hackel for (i = 0; i < ARRAY_SIZE(octets); i++) { 342*0c83ed8eSKurt Hackel if (octets[i] > 255) 343*0c83ed8eSKurt Hackel return -ERANGE; 344*0c83ed8eSKurt Hackel be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); 345*0c83ed8eSKurt Hackel } 346*0c83ed8eSKurt Hackel 347*0c83ed8eSKurt Hackel ret = 0; 348*0c83ed8eSKurt Hackel write_lock(&cluster->cl_nodes_lock); 349*0c83ed8eSKurt Hackel if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) 350*0c83ed8eSKurt Hackel ret = -EEXIST; 351*0c83ed8eSKurt Hackel else { 352*0c83ed8eSKurt Hackel rb_link_node(&node->nd_ip_node, parent, p); 353*0c83ed8eSKurt Hackel rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); 354*0c83ed8eSKurt Hackel } 355*0c83ed8eSKurt Hackel write_unlock(&cluster->cl_nodes_lock); 356*0c83ed8eSKurt Hackel if (ret) 357*0c83ed8eSKurt Hackel return ret; 358*0c83ed8eSKurt Hackel 359*0c83ed8eSKurt Hackel memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr)); 360*0c83ed8eSKurt Hackel 361*0c83ed8eSKurt Hackel return count; 362*0c83ed8eSKurt Hackel } 363*0c83ed8eSKurt Hackel 364*0c83ed8eSKurt Hackel static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page) 365*0c83ed8eSKurt Hackel { 366*0c83ed8eSKurt Hackel return sprintf(page, "%d\n", node->nd_local); 367*0c83ed8eSKurt Hackel } 368*0c83ed8eSKurt Hackel 369*0c83ed8eSKurt Hackel static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page, 370*0c83ed8eSKurt Hackel size_t count) 371*0c83ed8eSKurt Hackel { 372*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); 373*0c83ed8eSKurt Hackel unsigned long tmp; 374*0c83ed8eSKurt Hackel char *p = (char *)page; 375*0c83ed8eSKurt Hackel ssize_t ret; 376*0c83ed8eSKurt Hackel 377*0c83ed8eSKurt Hackel tmp = simple_strtoul(p, &p, 0); 378*0c83ed8eSKurt Hackel if (!p || (*p && (*p != '\n'))) 379*0c83ed8eSKurt Hackel return -EINVAL; 380*0c83ed8eSKurt Hackel 381*0c83ed8eSKurt Hackel tmp = !!tmp; /* boolean of whether this node wants to be local */ 382*0c83ed8eSKurt Hackel 383*0c83ed8eSKurt Hackel /* setting local turns on networking rx for now so we require having 384*0c83ed8eSKurt Hackel * set everything else first */ 385*0c83ed8eSKurt Hackel if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) || 386*0c83ed8eSKurt Hackel !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) || 387*0c83ed8eSKurt Hackel !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) 388*0c83ed8eSKurt Hackel return -EINVAL; /* XXX */ 389*0c83ed8eSKurt Hackel 390*0c83ed8eSKurt Hackel /* the only failure case is trying to set a new local node 391*0c83ed8eSKurt Hackel * when a different one is already set */ 392*0c83ed8eSKurt Hackel if (tmp && tmp == cluster->cl_has_local && 393*0c83ed8eSKurt Hackel cluster->cl_local_node != node->nd_num) 394*0c83ed8eSKurt Hackel return -EBUSY; 395*0c83ed8eSKurt Hackel 396*0c83ed8eSKurt Hackel /* bring up the rx thread if we're setting the new local node. */ 397*0c83ed8eSKurt Hackel if (tmp && !cluster->cl_has_local) { 398*0c83ed8eSKurt Hackel ret = o2net_start_listening(node); 399*0c83ed8eSKurt Hackel if (ret) 400*0c83ed8eSKurt Hackel return ret; 401*0c83ed8eSKurt Hackel } 402*0c83ed8eSKurt Hackel 403*0c83ed8eSKurt Hackel if (!tmp && cluster->cl_has_local && 404*0c83ed8eSKurt Hackel cluster->cl_local_node == node->nd_num) { 405*0c83ed8eSKurt Hackel o2net_stop_listening(node); 406*0c83ed8eSKurt Hackel cluster->cl_local_node = O2NM_INVALID_NODE_NUM; 407*0c83ed8eSKurt Hackel } 408*0c83ed8eSKurt Hackel 409*0c83ed8eSKurt Hackel node->nd_local = tmp; 410*0c83ed8eSKurt Hackel if (node->nd_local) { 411*0c83ed8eSKurt Hackel cluster->cl_has_local = tmp; 412*0c83ed8eSKurt Hackel cluster->cl_local_node = node->nd_num; 413*0c83ed8eSKurt Hackel } 414*0c83ed8eSKurt Hackel 415*0c83ed8eSKurt Hackel return count; 416*0c83ed8eSKurt Hackel } 417*0c83ed8eSKurt Hackel 418*0c83ed8eSKurt Hackel struct o2nm_node_attribute { 419*0c83ed8eSKurt Hackel struct configfs_attribute attr; 420*0c83ed8eSKurt Hackel ssize_t (*show)(struct o2nm_node *, char *); 421*0c83ed8eSKurt Hackel ssize_t (*store)(struct o2nm_node *, const char *, size_t); 422*0c83ed8eSKurt Hackel }; 423*0c83ed8eSKurt Hackel 424*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_num = { 425*0c83ed8eSKurt Hackel .attr = { .ca_owner = THIS_MODULE, 426*0c83ed8eSKurt Hackel .ca_name = "num", 427*0c83ed8eSKurt Hackel .ca_mode = S_IRUGO | S_IWUSR }, 428*0c83ed8eSKurt Hackel .show = o2nm_node_num_read, 429*0c83ed8eSKurt Hackel .store = o2nm_node_num_write, 430*0c83ed8eSKurt Hackel }; 431*0c83ed8eSKurt Hackel 432*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_ipv4_port = { 433*0c83ed8eSKurt Hackel .attr = { .ca_owner = THIS_MODULE, 434*0c83ed8eSKurt Hackel .ca_name = "ipv4_port", 435*0c83ed8eSKurt Hackel .ca_mode = S_IRUGO | S_IWUSR }, 436*0c83ed8eSKurt Hackel .show = o2nm_node_ipv4_port_read, 437*0c83ed8eSKurt Hackel .store = o2nm_node_ipv4_port_write, 438*0c83ed8eSKurt Hackel }; 439*0c83ed8eSKurt Hackel 440*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_ipv4_address = { 441*0c83ed8eSKurt Hackel .attr = { .ca_owner = THIS_MODULE, 442*0c83ed8eSKurt Hackel .ca_name = "ipv4_address", 443*0c83ed8eSKurt Hackel .ca_mode = S_IRUGO | S_IWUSR }, 444*0c83ed8eSKurt Hackel .show = o2nm_node_ipv4_address_read, 445*0c83ed8eSKurt Hackel .store = o2nm_node_ipv4_address_write, 446*0c83ed8eSKurt Hackel }; 447*0c83ed8eSKurt Hackel 448*0c83ed8eSKurt Hackel static struct o2nm_node_attribute o2nm_node_attr_local = { 449*0c83ed8eSKurt Hackel .attr = { .ca_owner = THIS_MODULE, 450*0c83ed8eSKurt Hackel .ca_name = "local", 451*0c83ed8eSKurt Hackel .ca_mode = S_IRUGO | S_IWUSR }, 452*0c83ed8eSKurt Hackel .show = o2nm_node_local_read, 453*0c83ed8eSKurt Hackel .store = o2nm_node_local_write, 454*0c83ed8eSKurt Hackel }; 455*0c83ed8eSKurt Hackel 456*0c83ed8eSKurt Hackel static struct configfs_attribute *o2nm_node_attrs[] = { 457*0c83ed8eSKurt Hackel [O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr, 458*0c83ed8eSKurt Hackel [O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr, 459*0c83ed8eSKurt Hackel [O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr, 460*0c83ed8eSKurt Hackel [O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr, 461*0c83ed8eSKurt Hackel NULL, 462*0c83ed8eSKurt Hackel }; 463*0c83ed8eSKurt Hackel 464*0c83ed8eSKurt Hackel static int o2nm_attr_index(struct configfs_attribute *attr) 465*0c83ed8eSKurt Hackel { 466*0c83ed8eSKurt Hackel int i; 467*0c83ed8eSKurt Hackel for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) { 468*0c83ed8eSKurt Hackel if (attr == o2nm_node_attrs[i]) 469*0c83ed8eSKurt Hackel return i; 470*0c83ed8eSKurt Hackel } 471*0c83ed8eSKurt Hackel BUG(); 472*0c83ed8eSKurt Hackel return 0; 473*0c83ed8eSKurt Hackel } 474*0c83ed8eSKurt Hackel 475*0c83ed8eSKurt Hackel static ssize_t o2nm_node_show(struct config_item *item, 476*0c83ed8eSKurt Hackel struct configfs_attribute *attr, 477*0c83ed8eSKurt Hackel char *page) 478*0c83ed8eSKurt Hackel { 479*0c83ed8eSKurt Hackel struct o2nm_node *node = to_o2nm_node(item); 480*0c83ed8eSKurt Hackel struct o2nm_node_attribute *o2nm_node_attr = 481*0c83ed8eSKurt Hackel container_of(attr, struct o2nm_node_attribute, attr); 482*0c83ed8eSKurt Hackel ssize_t ret = 0; 483*0c83ed8eSKurt Hackel 484*0c83ed8eSKurt Hackel if (o2nm_node_attr->show) 485*0c83ed8eSKurt Hackel ret = o2nm_node_attr->show(node, page); 486*0c83ed8eSKurt Hackel return ret; 487*0c83ed8eSKurt Hackel } 488*0c83ed8eSKurt Hackel 489*0c83ed8eSKurt Hackel static ssize_t o2nm_node_store(struct config_item *item, 490*0c83ed8eSKurt Hackel struct configfs_attribute *attr, 491*0c83ed8eSKurt Hackel const char *page, size_t count) 492*0c83ed8eSKurt Hackel { 493*0c83ed8eSKurt Hackel struct o2nm_node *node = to_o2nm_node(item); 494*0c83ed8eSKurt Hackel struct o2nm_node_attribute *o2nm_node_attr = 495*0c83ed8eSKurt Hackel container_of(attr, struct o2nm_node_attribute, attr); 496*0c83ed8eSKurt Hackel ssize_t ret; 497*0c83ed8eSKurt Hackel int attr_index = o2nm_attr_index(attr); 498*0c83ed8eSKurt Hackel 499*0c83ed8eSKurt Hackel if (o2nm_node_attr->store == NULL) { 500*0c83ed8eSKurt Hackel ret = -EINVAL; 501*0c83ed8eSKurt Hackel goto out; 502*0c83ed8eSKurt Hackel } 503*0c83ed8eSKurt Hackel 504*0c83ed8eSKurt Hackel if (test_bit(attr_index, &node->nd_set_attributes)) 505*0c83ed8eSKurt Hackel return -EBUSY; 506*0c83ed8eSKurt Hackel 507*0c83ed8eSKurt Hackel ret = o2nm_node_attr->store(node, page, count); 508*0c83ed8eSKurt Hackel if (ret < count) 509*0c83ed8eSKurt Hackel goto out; 510*0c83ed8eSKurt Hackel 511*0c83ed8eSKurt Hackel set_bit(attr_index, &node->nd_set_attributes); 512*0c83ed8eSKurt Hackel out: 513*0c83ed8eSKurt Hackel return ret; 514*0c83ed8eSKurt Hackel } 515*0c83ed8eSKurt Hackel 516*0c83ed8eSKurt Hackel static struct configfs_item_operations o2nm_node_item_ops = { 517*0c83ed8eSKurt Hackel .release = o2nm_node_release, 518*0c83ed8eSKurt Hackel .show_attribute = o2nm_node_show, 519*0c83ed8eSKurt Hackel .store_attribute = o2nm_node_store, 520*0c83ed8eSKurt Hackel }; 521*0c83ed8eSKurt Hackel 522*0c83ed8eSKurt Hackel static struct config_item_type o2nm_node_type = { 523*0c83ed8eSKurt Hackel .ct_item_ops = &o2nm_node_item_ops, 524*0c83ed8eSKurt Hackel .ct_attrs = o2nm_node_attrs, 525*0c83ed8eSKurt Hackel .ct_owner = THIS_MODULE, 526*0c83ed8eSKurt Hackel }; 527*0c83ed8eSKurt Hackel 528*0c83ed8eSKurt Hackel /* node set */ 529*0c83ed8eSKurt Hackel 530*0c83ed8eSKurt Hackel struct o2nm_node_group { 531*0c83ed8eSKurt Hackel struct config_group ns_group; 532*0c83ed8eSKurt Hackel /* some stuff? */ 533*0c83ed8eSKurt Hackel }; 534*0c83ed8eSKurt Hackel 535*0c83ed8eSKurt Hackel #if 0 536*0c83ed8eSKurt Hackel static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group) 537*0c83ed8eSKurt Hackel { 538*0c83ed8eSKurt Hackel return group ? 539*0c83ed8eSKurt Hackel container_of(group, struct o2nm_node_group, ns_group) 540*0c83ed8eSKurt Hackel : NULL; 541*0c83ed8eSKurt Hackel } 542*0c83ed8eSKurt Hackel #endif 543*0c83ed8eSKurt Hackel 544*0c83ed8eSKurt Hackel static struct config_item *o2nm_node_group_make_item(struct config_group *group, 545*0c83ed8eSKurt Hackel const char *name) 546*0c83ed8eSKurt Hackel { 547*0c83ed8eSKurt Hackel struct o2nm_node *node = NULL; 548*0c83ed8eSKurt Hackel struct config_item *ret = NULL; 549*0c83ed8eSKurt Hackel 550*0c83ed8eSKurt Hackel if (strlen(name) > O2NM_MAX_NAME_LEN) 551*0c83ed8eSKurt Hackel goto out; /* ENAMETOOLONG */ 552*0c83ed8eSKurt Hackel 553*0c83ed8eSKurt Hackel node = kcalloc(1, sizeof(struct o2nm_node), GFP_KERNEL); 554*0c83ed8eSKurt Hackel if (node == NULL) 555*0c83ed8eSKurt Hackel goto out; /* ENOMEM */ 556*0c83ed8eSKurt Hackel 557*0c83ed8eSKurt Hackel strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ 558*0c83ed8eSKurt Hackel config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); 559*0c83ed8eSKurt Hackel spin_lock_init(&node->nd_lock); 560*0c83ed8eSKurt Hackel 561*0c83ed8eSKurt Hackel ret = &node->nd_item; 562*0c83ed8eSKurt Hackel 563*0c83ed8eSKurt Hackel out: 564*0c83ed8eSKurt Hackel if (ret == NULL) 565*0c83ed8eSKurt Hackel kfree(node); 566*0c83ed8eSKurt Hackel 567*0c83ed8eSKurt Hackel return ret; 568*0c83ed8eSKurt Hackel } 569*0c83ed8eSKurt Hackel 570*0c83ed8eSKurt Hackel static void o2nm_node_group_drop_item(struct config_group *group, 571*0c83ed8eSKurt Hackel struct config_item *item) 572*0c83ed8eSKurt Hackel { 573*0c83ed8eSKurt Hackel struct o2nm_node *node = to_o2nm_node(item); 574*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent); 575*0c83ed8eSKurt Hackel 576*0c83ed8eSKurt Hackel o2net_disconnect_node(node); 577*0c83ed8eSKurt Hackel 578*0c83ed8eSKurt Hackel if (cluster->cl_has_local && 579*0c83ed8eSKurt Hackel (cluster->cl_local_node == node->nd_num)) { 580*0c83ed8eSKurt Hackel cluster->cl_has_local = 0; 581*0c83ed8eSKurt Hackel cluster->cl_local_node = O2NM_INVALID_NODE_NUM; 582*0c83ed8eSKurt Hackel o2net_stop_listening(node); 583*0c83ed8eSKurt Hackel } 584*0c83ed8eSKurt Hackel 585*0c83ed8eSKurt Hackel /* XXX call into net to stop this node from trading messages */ 586*0c83ed8eSKurt Hackel 587*0c83ed8eSKurt Hackel write_lock(&cluster->cl_nodes_lock); 588*0c83ed8eSKurt Hackel 589*0c83ed8eSKurt Hackel /* XXX sloppy */ 590*0c83ed8eSKurt Hackel if (node->nd_ipv4_address) 591*0c83ed8eSKurt Hackel rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree); 592*0c83ed8eSKurt Hackel 593*0c83ed8eSKurt Hackel /* nd_num might be 0 if the node number hasn't been set.. */ 594*0c83ed8eSKurt Hackel if (cluster->cl_nodes[node->nd_num] == node) { 595*0c83ed8eSKurt Hackel cluster->cl_nodes[node->nd_num] = NULL; 596*0c83ed8eSKurt Hackel clear_bit(node->nd_num, cluster->cl_nodes_bitmap); 597*0c83ed8eSKurt Hackel } 598*0c83ed8eSKurt Hackel write_unlock(&cluster->cl_nodes_lock); 599*0c83ed8eSKurt Hackel 600*0c83ed8eSKurt Hackel config_item_put(item); 601*0c83ed8eSKurt Hackel } 602*0c83ed8eSKurt Hackel 603*0c83ed8eSKurt Hackel static struct configfs_group_operations o2nm_node_group_group_ops = { 604*0c83ed8eSKurt Hackel .make_item = o2nm_node_group_make_item, 605*0c83ed8eSKurt Hackel .drop_item = o2nm_node_group_drop_item, 606*0c83ed8eSKurt Hackel }; 607*0c83ed8eSKurt Hackel 608*0c83ed8eSKurt Hackel static struct config_item_type o2nm_node_group_type = { 609*0c83ed8eSKurt Hackel .ct_group_ops = &o2nm_node_group_group_ops, 610*0c83ed8eSKurt Hackel .ct_owner = THIS_MODULE, 611*0c83ed8eSKurt Hackel }; 612*0c83ed8eSKurt Hackel 613*0c83ed8eSKurt Hackel /* cluster */ 614*0c83ed8eSKurt Hackel 615*0c83ed8eSKurt Hackel static void o2nm_cluster_release(struct config_item *item) 616*0c83ed8eSKurt Hackel { 617*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = to_o2nm_cluster(item); 618*0c83ed8eSKurt Hackel 619*0c83ed8eSKurt Hackel kfree(cluster->cl_group.default_groups); 620*0c83ed8eSKurt Hackel kfree(cluster); 621*0c83ed8eSKurt Hackel } 622*0c83ed8eSKurt Hackel 623*0c83ed8eSKurt Hackel static struct configfs_item_operations o2nm_cluster_item_ops = { 624*0c83ed8eSKurt Hackel .release = o2nm_cluster_release, 625*0c83ed8eSKurt Hackel }; 626*0c83ed8eSKurt Hackel 627*0c83ed8eSKurt Hackel static struct config_item_type o2nm_cluster_type = { 628*0c83ed8eSKurt Hackel .ct_item_ops = &o2nm_cluster_item_ops, 629*0c83ed8eSKurt Hackel .ct_owner = THIS_MODULE, 630*0c83ed8eSKurt Hackel }; 631*0c83ed8eSKurt Hackel 632*0c83ed8eSKurt Hackel /* cluster set */ 633*0c83ed8eSKurt Hackel 634*0c83ed8eSKurt Hackel struct o2nm_cluster_group { 635*0c83ed8eSKurt Hackel struct configfs_subsystem cs_subsys; 636*0c83ed8eSKurt Hackel /* some stuff? */ 637*0c83ed8eSKurt Hackel }; 638*0c83ed8eSKurt Hackel 639*0c83ed8eSKurt Hackel #if 0 640*0c83ed8eSKurt Hackel static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group) 641*0c83ed8eSKurt Hackel { 642*0c83ed8eSKurt Hackel return group ? 643*0c83ed8eSKurt Hackel container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys) 644*0c83ed8eSKurt Hackel : NULL; 645*0c83ed8eSKurt Hackel } 646*0c83ed8eSKurt Hackel #endif 647*0c83ed8eSKurt Hackel 648*0c83ed8eSKurt Hackel static struct config_group *o2nm_cluster_group_make_group(struct config_group *group, 649*0c83ed8eSKurt Hackel const char *name) 650*0c83ed8eSKurt Hackel { 651*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = NULL; 652*0c83ed8eSKurt Hackel struct o2nm_node_group *ns = NULL; 653*0c83ed8eSKurt Hackel struct config_group *o2hb_group = NULL, *ret = NULL; 654*0c83ed8eSKurt Hackel void *defs = NULL; 655*0c83ed8eSKurt Hackel 656*0c83ed8eSKurt Hackel /* this runs under the parent dir's i_sem; there can be only 657*0c83ed8eSKurt Hackel * one caller in here at a time */ 658*0c83ed8eSKurt Hackel if (o2nm_single_cluster) 659*0c83ed8eSKurt Hackel goto out; /* ENOSPC */ 660*0c83ed8eSKurt Hackel 661*0c83ed8eSKurt Hackel cluster = kcalloc(1, sizeof(struct o2nm_cluster), GFP_KERNEL); 662*0c83ed8eSKurt Hackel ns = kcalloc(1, sizeof(struct o2nm_node_group), GFP_KERNEL); 663*0c83ed8eSKurt Hackel defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); 664*0c83ed8eSKurt Hackel o2hb_group = o2hb_alloc_hb_set(); 665*0c83ed8eSKurt Hackel if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) 666*0c83ed8eSKurt Hackel goto out; 667*0c83ed8eSKurt Hackel 668*0c83ed8eSKurt Hackel config_group_init_type_name(&cluster->cl_group, name, 669*0c83ed8eSKurt Hackel &o2nm_cluster_type); 670*0c83ed8eSKurt Hackel config_group_init_type_name(&ns->ns_group, "node", 671*0c83ed8eSKurt Hackel &o2nm_node_group_type); 672*0c83ed8eSKurt Hackel 673*0c83ed8eSKurt Hackel cluster->cl_group.default_groups = defs; 674*0c83ed8eSKurt Hackel cluster->cl_group.default_groups[0] = &ns->ns_group; 675*0c83ed8eSKurt Hackel cluster->cl_group.default_groups[1] = o2hb_group; 676*0c83ed8eSKurt Hackel cluster->cl_group.default_groups[2] = NULL; 677*0c83ed8eSKurt Hackel rwlock_init(&cluster->cl_nodes_lock); 678*0c83ed8eSKurt Hackel cluster->cl_node_ip_tree = RB_ROOT; 679*0c83ed8eSKurt Hackel 680*0c83ed8eSKurt Hackel ret = &cluster->cl_group; 681*0c83ed8eSKurt Hackel o2nm_single_cluster = cluster; 682*0c83ed8eSKurt Hackel 683*0c83ed8eSKurt Hackel out: 684*0c83ed8eSKurt Hackel if (ret == NULL) { 685*0c83ed8eSKurt Hackel kfree(cluster); 686*0c83ed8eSKurt Hackel kfree(ns); 687*0c83ed8eSKurt Hackel o2hb_free_hb_set(o2hb_group); 688*0c83ed8eSKurt Hackel kfree(defs); 689*0c83ed8eSKurt Hackel } 690*0c83ed8eSKurt Hackel 691*0c83ed8eSKurt Hackel return ret; 692*0c83ed8eSKurt Hackel } 693*0c83ed8eSKurt Hackel 694*0c83ed8eSKurt Hackel static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item) 695*0c83ed8eSKurt Hackel { 696*0c83ed8eSKurt Hackel struct o2nm_cluster *cluster = to_o2nm_cluster(item); 697*0c83ed8eSKurt Hackel int i; 698*0c83ed8eSKurt Hackel struct config_item *killme; 699*0c83ed8eSKurt Hackel 700*0c83ed8eSKurt Hackel BUG_ON(o2nm_single_cluster != cluster); 701*0c83ed8eSKurt Hackel o2nm_single_cluster = NULL; 702*0c83ed8eSKurt Hackel 703*0c83ed8eSKurt Hackel for (i = 0; cluster->cl_group.default_groups[i]; i++) { 704*0c83ed8eSKurt Hackel killme = &cluster->cl_group.default_groups[i]->cg_item; 705*0c83ed8eSKurt Hackel cluster->cl_group.default_groups[i] = NULL; 706*0c83ed8eSKurt Hackel config_item_put(killme); 707*0c83ed8eSKurt Hackel } 708*0c83ed8eSKurt Hackel 709*0c83ed8eSKurt Hackel config_item_put(item); 710*0c83ed8eSKurt Hackel } 711*0c83ed8eSKurt Hackel 712*0c83ed8eSKurt Hackel static struct configfs_group_operations o2nm_cluster_group_group_ops = { 713*0c83ed8eSKurt Hackel .make_group = o2nm_cluster_group_make_group, 714*0c83ed8eSKurt Hackel .drop_item = o2nm_cluster_group_drop_item, 715*0c83ed8eSKurt Hackel }; 716*0c83ed8eSKurt Hackel 717*0c83ed8eSKurt Hackel static struct config_item_type o2nm_cluster_group_type = { 718*0c83ed8eSKurt Hackel .ct_group_ops = &o2nm_cluster_group_group_ops, 719*0c83ed8eSKurt Hackel .ct_owner = THIS_MODULE, 720*0c83ed8eSKurt Hackel }; 721*0c83ed8eSKurt Hackel 722*0c83ed8eSKurt Hackel static struct o2nm_cluster_group o2nm_cluster_group = { 723*0c83ed8eSKurt Hackel .cs_subsys = { 724*0c83ed8eSKurt Hackel .su_group = { 725*0c83ed8eSKurt Hackel .cg_item = { 726*0c83ed8eSKurt Hackel .ci_namebuf = "cluster", 727*0c83ed8eSKurt Hackel .ci_type = &o2nm_cluster_group_type, 728*0c83ed8eSKurt Hackel }, 729*0c83ed8eSKurt Hackel }, 730*0c83ed8eSKurt Hackel }, 731*0c83ed8eSKurt Hackel }; 732*0c83ed8eSKurt Hackel 733*0c83ed8eSKurt Hackel static void __exit exit_o2nm(void) 734*0c83ed8eSKurt Hackel { 735*0c83ed8eSKurt Hackel if (ocfs2_table_header) 736*0c83ed8eSKurt Hackel unregister_sysctl_table(ocfs2_table_header); 737*0c83ed8eSKurt Hackel 738*0c83ed8eSKurt Hackel /* XXX sync with hb callbacks and shut down hb? */ 739*0c83ed8eSKurt Hackel o2net_unregister_hb_callbacks(); 740*0c83ed8eSKurt Hackel configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); 741*0c83ed8eSKurt Hackel o2cb_sys_shutdown(); 742*0c83ed8eSKurt Hackel 743*0c83ed8eSKurt Hackel o2net_exit(); 744*0c83ed8eSKurt Hackel } 745*0c83ed8eSKurt Hackel 746*0c83ed8eSKurt Hackel static int __init init_o2nm(void) 747*0c83ed8eSKurt Hackel { 748*0c83ed8eSKurt Hackel int ret = -1; 749*0c83ed8eSKurt Hackel 750*0c83ed8eSKurt Hackel cluster_print_version(); 751*0c83ed8eSKurt Hackel 752*0c83ed8eSKurt Hackel o2hb_init(); 753*0c83ed8eSKurt Hackel o2net_init(); 754*0c83ed8eSKurt Hackel 755*0c83ed8eSKurt Hackel ocfs2_table_header = register_sysctl_table(ocfs2_root_table, 0); 756*0c83ed8eSKurt Hackel if (!ocfs2_table_header) { 757*0c83ed8eSKurt Hackel printk(KERN_ERR "nodemanager: unable to register sysctl\n"); 758*0c83ed8eSKurt Hackel ret = -ENOMEM; /* or something. */ 759*0c83ed8eSKurt Hackel goto out; 760*0c83ed8eSKurt Hackel } 761*0c83ed8eSKurt Hackel 762*0c83ed8eSKurt Hackel ret = o2net_register_hb_callbacks(); 763*0c83ed8eSKurt Hackel if (ret) 764*0c83ed8eSKurt Hackel goto out_sysctl; 765*0c83ed8eSKurt Hackel 766*0c83ed8eSKurt Hackel config_group_init(&o2nm_cluster_group.cs_subsys.su_group); 767*0c83ed8eSKurt Hackel init_MUTEX(&o2nm_cluster_group.cs_subsys.su_sem); 768*0c83ed8eSKurt Hackel ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys); 769*0c83ed8eSKurt Hackel if (ret) { 770*0c83ed8eSKurt Hackel printk(KERN_ERR "nodemanager: Registration returned %d\n", ret); 771*0c83ed8eSKurt Hackel goto out_callbacks; 772*0c83ed8eSKurt Hackel } 773*0c83ed8eSKurt Hackel 774*0c83ed8eSKurt Hackel ret = o2cb_sys_init(); 775*0c83ed8eSKurt Hackel if (!ret) 776*0c83ed8eSKurt Hackel goto out; 777*0c83ed8eSKurt Hackel 778*0c83ed8eSKurt Hackel configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys); 779*0c83ed8eSKurt Hackel out_callbacks: 780*0c83ed8eSKurt Hackel o2net_unregister_hb_callbacks(); 781*0c83ed8eSKurt Hackel out_sysctl: 782*0c83ed8eSKurt Hackel unregister_sysctl_table(ocfs2_table_header); 783*0c83ed8eSKurt Hackel out: 784*0c83ed8eSKurt Hackel return ret; 785*0c83ed8eSKurt Hackel } 786*0c83ed8eSKurt Hackel 787*0c83ed8eSKurt Hackel MODULE_AUTHOR("Oracle"); 788*0c83ed8eSKurt Hackel MODULE_LICENSE("GPL"); 789*0c83ed8eSKurt Hackel 790*0c83ed8eSKurt Hackel module_init(init_o2nm) 791*0c83ed8eSKurt Hackel module_exit(exit_o2nm) 792