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