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