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