Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20-rc4 789 lines 19 kB view raw
1/****************************************************************************** 2******************************************************************************* 3** 4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 5** Copyright (C) 2004-2005 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 <net/sock.h> 18 19#include "config.h" 20#include "lowcomms.h" 21 22/* 23 * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid 24 * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight 25 * /config/dlm/<cluster>/comms/<comm>/nodeid 26 * /config/dlm/<cluster>/comms/<comm>/local 27 * /config/dlm/<cluster>/comms/<comm>/addr 28 * The <cluster> level is useless, but I haven't figured out how to avoid it. 29 */ 30 31static struct config_group *space_list; 32static struct config_group *comm_list; 33static struct comm *local_comm; 34 35struct clusters; 36struct cluster; 37struct spaces; 38struct space; 39struct comms; 40struct comm; 41struct nodes; 42struct node; 43 44static struct config_group *make_cluster(struct config_group *, const char *); 45static void drop_cluster(struct config_group *, struct config_item *); 46static void release_cluster(struct config_item *); 47static struct config_group *make_space(struct config_group *, const char *); 48static void drop_space(struct config_group *, struct config_item *); 49static void release_space(struct config_item *); 50static struct config_item *make_comm(struct config_group *, const char *); 51static void drop_comm(struct config_group *, struct config_item *); 52static void release_comm(struct config_item *); 53static struct config_item *make_node(struct config_group *, const char *); 54static void drop_node(struct config_group *, struct config_item *); 55static void release_node(struct config_item *); 56 57static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, 58 char *buf); 59static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, 60 const char *buf, size_t len); 61static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, 62 char *buf); 63static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, 64 const char *buf, size_t len); 65 66static ssize_t comm_nodeid_read(struct comm *cm, char *buf); 67static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len); 68static ssize_t comm_local_read(struct comm *cm, char *buf); 69static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len); 70static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len); 71static ssize_t node_nodeid_read(struct node *nd, char *buf); 72static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len); 73static ssize_t node_weight_read(struct node *nd, char *buf); 74static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len); 75 76enum { 77 COMM_ATTR_NODEID = 0, 78 COMM_ATTR_LOCAL, 79 COMM_ATTR_ADDR, 80}; 81 82struct comm_attribute { 83 struct configfs_attribute attr; 84 ssize_t (*show)(struct comm *, char *); 85 ssize_t (*store)(struct comm *, const char *, size_t); 86}; 87 88static struct comm_attribute comm_attr_nodeid = { 89 .attr = { .ca_owner = THIS_MODULE, 90 .ca_name = "nodeid", 91 .ca_mode = S_IRUGO | S_IWUSR }, 92 .show = comm_nodeid_read, 93 .store = comm_nodeid_write, 94}; 95 96static struct comm_attribute comm_attr_local = { 97 .attr = { .ca_owner = THIS_MODULE, 98 .ca_name = "local", 99 .ca_mode = S_IRUGO | S_IWUSR }, 100 .show = comm_local_read, 101 .store = comm_local_write, 102}; 103 104static struct comm_attribute comm_attr_addr = { 105 .attr = { .ca_owner = THIS_MODULE, 106 .ca_name = "addr", 107 .ca_mode = S_IRUGO | S_IWUSR }, 108 .store = comm_addr_write, 109}; 110 111static struct configfs_attribute *comm_attrs[] = { 112 [COMM_ATTR_NODEID] = &comm_attr_nodeid.attr, 113 [COMM_ATTR_LOCAL] = &comm_attr_local.attr, 114 [COMM_ATTR_ADDR] = &comm_attr_addr.attr, 115 NULL, 116}; 117 118enum { 119 NODE_ATTR_NODEID = 0, 120 NODE_ATTR_WEIGHT, 121}; 122 123struct node_attribute { 124 struct configfs_attribute attr; 125 ssize_t (*show)(struct node *, char *); 126 ssize_t (*store)(struct node *, const char *, size_t); 127}; 128 129static struct node_attribute node_attr_nodeid = { 130 .attr = { .ca_owner = THIS_MODULE, 131 .ca_name = "nodeid", 132 .ca_mode = S_IRUGO | S_IWUSR }, 133 .show = node_nodeid_read, 134 .store = node_nodeid_write, 135}; 136 137static struct node_attribute node_attr_weight = { 138 .attr = { .ca_owner = THIS_MODULE, 139 .ca_name = "weight", 140 .ca_mode = S_IRUGO | S_IWUSR }, 141 .show = node_weight_read, 142 .store = node_weight_write, 143}; 144 145static struct configfs_attribute *node_attrs[] = { 146 [NODE_ATTR_NODEID] = &node_attr_nodeid.attr, 147 [NODE_ATTR_WEIGHT] = &node_attr_weight.attr, 148 NULL, 149}; 150 151struct clusters { 152 struct configfs_subsystem subsys; 153}; 154 155struct cluster { 156 struct config_group group; 157}; 158 159struct spaces { 160 struct config_group ss_group; 161}; 162 163struct space { 164 struct config_group group; 165 struct list_head members; 166 struct mutex members_lock; 167 int members_count; 168}; 169 170struct comms { 171 struct config_group cs_group; 172}; 173 174struct comm { 175 struct config_item item; 176 int nodeid; 177 int local; 178 int addr_count; 179 struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; 180}; 181 182struct nodes { 183 struct config_group ns_group; 184}; 185 186struct node { 187 struct config_item item; 188 struct list_head list; /* space->members */ 189 int nodeid; 190 int weight; 191}; 192 193static struct configfs_group_operations clusters_ops = { 194 .make_group = make_cluster, 195 .drop_item = drop_cluster, 196}; 197 198static struct configfs_item_operations cluster_ops = { 199 .release = release_cluster, 200}; 201 202static struct configfs_group_operations spaces_ops = { 203 .make_group = make_space, 204 .drop_item = drop_space, 205}; 206 207static struct configfs_item_operations space_ops = { 208 .release = release_space, 209}; 210 211static struct configfs_group_operations comms_ops = { 212 .make_item = make_comm, 213 .drop_item = drop_comm, 214}; 215 216static struct configfs_item_operations comm_ops = { 217 .release = release_comm, 218 .show_attribute = show_comm, 219 .store_attribute = store_comm, 220}; 221 222static struct configfs_group_operations nodes_ops = { 223 .make_item = make_node, 224 .drop_item = drop_node, 225}; 226 227static struct configfs_item_operations node_ops = { 228 .release = release_node, 229 .show_attribute = show_node, 230 .store_attribute = store_node, 231}; 232 233static struct config_item_type clusters_type = { 234 .ct_group_ops = &clusters_ops, 235 .ct_owner = THIS_MODULE, 236}; 237 238static struct config_item_type cluster_type = { 239 .ct_item_ops = &cluster_ops, 240 .ct_owner = THIS_MODULE, 241}; 242 243static struct config_item_type spaces_type = { 244 .ct_group_ops = &spaces_ops, 245 .ct_owner = THIS_MODULE, 246}; 247 248static struct config_item_type space_type = { 249 .ct_item_ops = &space_ops, 250 .ct_owner = THIS_MODULE, 251}; 252 253static struct config_item_type comms_type = { 254 .ct_group_ops = &comms_ops, 255 .ct_owner = THIS_MODULE, 256}; 257 258static struct config_item_type comm_type = { 259 .ct_item_ops = &comm_ops, 260 .ct_attrs = comm_attrs, 261 .ct_owner = THIS_MODULE, 262}; 263 264static struct config_item_type nodes_type = { 265 .ct_group_ops = &nodes_ops, 266 .ct_owner = THIS_MODULE, 267}; 268 269static struct config_item_type node_type = { 270 .ct_item_ops = &node_ops, 271 .ct_attrs = node_attrs, 272 .ct_owner = THIS_MODULE, 273}; 274 275static struct cluster *to_cluster(struct config_item *i) 276{ 277 return i ? container_of(to_config_group(i), struct cluster, group):NULL; 278} 279 280static struct space *to_space(struct config_item *i) 281{ 282 return i ? container_of(to_config_group(i), struct space, group) : NULL; 283} 284 285static struct comm *to_comm(struct config_item *i) 286{ 287 return i ? container_of(i, struct comm, item) : NULL; 288} 289 290static struct node *to_node(struct config_item *i) 291{ 292 return i ? container_of(i, struct node, item) : NULL; 293} 294 295static struct config_group *make_cluster(struct config_group *g, 296 const char *name) 297{ 298 struct cluster *cl = NULL; 299 struct spaces *sps = NULL; 300 struct comms *cms = NULL; 301 void *gps = NULL; 302 303 cl = kzalloc(sizeof(struct cluster), GFP_KERNEL); 304 gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); 305 sps = kzalloc(sizeof(struct spaces), GFP_KERNEL); 306 cms = kzalloc(sizeof(struct comms), GFP_KERNEL); 307 308 if (!cl || !gps || !sps || !cms) 309 goto fail; 310 311 config_group_init_type_name(&cl->group, name, &cluster_type); 312 config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type); 313 config_group_init_type_name(&cms->cs_group, "comms", &comms_type); 314 315 cl->group.default_groups = gps; 316 cl->group.default_groups[0] = &sps->ss_group; 317 cl->group.default_groups[1] = &cms->cs_group; 318 cl->group.default_groups[2] = NULL; 319 320 space_list = &sps->ss_group; 321 comm_list = &cms->cs_group; 322 return &cl->group; 323 324 fail: 325 kfree(cl); 326 kfree(gps); 327 kfree(sps); 328 kfree(cms); 329 return NULL; 330} 331 332static void drop_cluster(struct config_group *g, struct config_item *i) 333{ 334 struct cluster *cl = to_cluster(i); 335 struct config_item *tmp; 336 int j; 337 338 for (j = 0; cl->group.default_groups[j]; j++) { 339 tmp = &cl->group.default_groups[j]->cg_item; 340 cl->group.default_groups[j] = NULL; 341 config_item_put(tmp); 342 } 343 344 space_list = NULL; 345 comm_list = NULL; 346 347 config_item_put(i); 348} 349 350static void release_cluster(struct config_item *i) 351{ 352 struct cluster *cl = to_cluster(i); 353 kfree(cl->group.default_groups); 354 kfree(cl); 355} 356 357static struct config_group *make_space(struct config_group *g, const char *name) 358{ 359 struct space *sp = NULL; 360 struct nodes *nds = NULL; 361 void *gps = NULL; 362 363 sp = kzalloc(sizeof(struct space), GFP_KERNEL); 364 gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL); 365 nds = kzalloc(sizeof(struct nodes), GFP_KERNEL); 366 367 if (!sp || !gps || !nds) 368 goto fail; 369 370 config_group_init_type_name(&sp->group, name, &space_type); 371 config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type); 372 373 sp->group.default_groups = gps; 374 sp->group.default_groups[0] = &nds->ns_group; 375 sp->group.default_groups[1] = NULL; 376 377 INIT_LIST_HEAD(&sp->members); 378 mutex_init(&sp->members_lock); 379 sp->members_count = 0; 380 return &sp->group; 381 382 fail: 383 kfree(sp); 384 kfree(gps); 385 kfree(nds); 386 return NULL; 387} 388 389static void drop_space(struct config_group *g, struct config_item *i) 390{ 391 struct space *sp = to_space(i); 392 struct config_item *tmp; 393 int j; 394 395 /* assert list_empty(&sp->members) */ 396 397 for (j = 0; sp->group.default_groups[j]; j++) { 398 tmp = &sp->group.default_groups[j]->cg_item; 399 sp->group.default_groups[j] = NULL; 400 config_item_put(tmp); 401 } 402 403 config_item_put(i); 404} 405 406static void release_space(struct config_item *i) 407{ 408 struct space *sp = to_space(i); 409 kfree(sp->group.default_groups); 410 kfree(sp); 411} 412 413static struct config_item *make_comm(struct config_group *g, const char *name) 414{ 415 struct comm *cm; 416 417 cm = kzalloc(sizeof(struct comm), GFP_KERNEL); 418 if (!cm) 419 return NULL; 420 421 config_item_init_type_name(&cm->item, name, &comm_type); 422 cm->nodeid = -1; 423 cm->local = 0; 424 cm->addr_count = 0; 425 return &cm->item; 426} 427 428static void drop_comm(struct config_group *g, struct config_item *i) 429{ 430 struct comm *cm = to_comm(i); 431 if (local_comm == cm) 432 local_comm = NULL; 433 dlm_lowcomms_close(cm->nodeid); 434 while (cm->addr_count--) 435 kfree(cm->addr[cm->addr_count]); 436 config_item_put(i); 437} 438 439static void release_comm(struct config_item *i) 440{ 441 struct comm *cm = to_comm(i); 442 kfree(cm); 443} 444 445static struct config_item *make_node(struct config_group *g, const char *name) 446{ 447 struct space *sp = to_space(g->cg_item.ci_parent); 448 struct node *nd; 449 450 nd = kzalloc(sizeof(struct node), GFP_KERNEL); 451 if (!nd) 452 return NULL; 453 454 config_item_init_type_name(&nd->item, name, &node_type); 455 nd->nodeid = -1; 456 nd->weight = 1; /* default weight of 1 if none is set */ 457 458 mutex_lock(&sp->members_lock); 459 list_add(&nd->list, &sp->members); 460 sp->members_count++; 461 mutex_unlock(&sp->members_lock); 462 463 return &nd->item; 464} 465 466static void drop_node(struct config_group *g, struct config_item *i) 467{ 468 struct space *sp = to_space(g->cg_item.ci_parent); 469 struct node *nd = to_node(i); 470 471 mutex_lock(&sp->members_lock); 472 list_del(&nd->list); 473 sp->members_count--; 474 mutex_unlock(&sp->members_lock); 475 476 config_item_put(i); 477} 478 479static void release_node(struct config_item *i) 480{ 481 struct node *nd = to_node(i); 482 kfree(nd); 483} 484 485static struct clusters clusters_root = { 486 .subsys = { 487 .su_group = { 488 .cg_item = { 489 .ci_namebuf = "dlm", 490 .ci_type = &clusters_type, 491 }, 492 }, 493 }, 494}; 495 496int dlm_config_init(void) 497{ 498 config_group_init(&clusters_root.subsys.su_group); 499 init_MUTEX(&clusters_root.subsys.su_sem); 500 return configfs_register_subsystem(&clusters_root.subsys); 501} 502 503void dlm_config_exit(void) 504{ 505 configfs_unregister_subsystem(&clusters_root.subsys); 506} 507 508/* 509 * Functions for user space to read/write attributes 510 */ 511 512static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, 513 char *buf) 514{ 515 struct comm *cm = to_comm(i); 516 struct comm_attribute *cma = 517 container_of(a, struct comm_attribute, attr); 518 return cma->show ? cma->show(cm, buf) : 0; 519} 520 521static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, 522 const char *buf, size_t len) 523{ 524 struct comm *cm = to_comm(i); 525 struct comm_attribute *cma = 526 container_of(a, struct comm_attribute, attr); 527 return cma->store ? cma->store(cm, buf, len) : -EINVAL; 528} 529 530static ssize_t comm_nodeid_read(struct comm *cm, char *buf) 531{ 532 return sprintf(buf, "%d\n", cm->nodeid); 533} 534 535static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len) 536{ 537 cm->nodeid = simple_strtol(buf, NULL, 0); 538 return len; 539} 540 541static ssize_t comm_local_read(struct comm *cm, char *buf) 542{ 543 return sprintf(buf, "%d\n", cm->local); 544} 545 546static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len) 547{ 548 cm->local= simple_strtol(buf, NULL, 0); 549 if (cm->local && !local_comm) 550 local_comm = cm; 551 return len; 552} 553 554static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len) 555{ 556 struct sockaddr_storage *addr; 557 558 if (len != sizeof(struct sockaddr_storage)) 559 return -EINVAL; 560 561 if (cm->addr_count >= DLM_MAX_ADDR_COUNT) 562 return -ENOSPC; 563 564 addr = kzalloc(sizeof(*addr), GFP_KERNEL); 565 if (!addr) 566 return -ENOMEM; 567 568 memcpy(addr, buf, len); 569 cm->addr[cm->addr_count++] = addr; 570 return len; 571} 572 573static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, 574 char *buf) 575{ 576 struct node *nd = to_node(i); 577 struct node_attribute *nda = 578 container_of(a, struct node_attribute, attr); 579 return nda->show ? nda->show(nd, buf) : 0; 580} 581 582static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, 583 const char *buf, size_t len) 584{ 585 struct node *nd = to_node(i); 586 struct node_attribute *nda = 587 container_of(a, struct node_attribute, attr); 588 return nda->store ? nda->store(nd, buf, len) : -EINVAL; 589} 590 591static ssize_t node_nodeid_read(struct node *nd, char *buf) 592{ 593 return sprintf(buf, "%d\n", nd->nodeid); 594} 595 596static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len) 597{ 598 nd->nodeid = simple_strtol(buf, NULL, 0); 599 return len; 600} 601 602static ssize_t node_weight_read(struct node *nd, char *buf) 603{ 604 return sprintf(buf, "%d\n", nd->weight); 605} 606 607static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len) 608{ 609 nd->weight = simple_strtol(buf, NULL, 0); 610 return len; 611} 612 613/* 614 * Functions for the dlm to get the info that's been configured 615 */ 616 617static struct space *get_space(char *name) 618{ 619 if (!space_list) 620 return NULL; 621 return to_space(config_group_find_obj(space_list, name)); 622} 623 624static void put_space(struct space *sp) 625{ 626 config_item_put(&sp->group.cg_item); 627} 628 629static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr) 630{ 631 struct config_item *i; 632 struct comm *cm = NULL; 633 int found = 0; 634 635 if (!comm_list) 636 return NULL; 637 638 down(&clusters_root.subsys.su_sem); 639 640 list_for_each_entry(i, &comm_list->cg_children, ci_entry) { 641 cm = to_comm(i); 642 643 if (nodeid) { 644 if (cm->nodeid != nodeid) 645 continue; 646 found = 1; 647 break; 648 } else { 649 if (!cm->addr_count || 650 memcmp(cm->addr[0], addr, sizeof(*addr))) 651 continue; 652 found = 1; 653 break; 654 } 655 } 656 up(&clusters_root.subsys.su_sem); 657 658 if (found) 659 config_item_get(i); 660 else 661 cm = NULL; 662 return cm; 663} 664 665static void put_comm(struct comm *cm) 666{ 667 config_item_put(&cm->item); 668} 669 670/* caller must free mem */ 671int dlm_nodeid_list(char *lsname, int **ids_out) 672{ 673 struct space *sp; 674 struct node *nd; 675 int i = 0, rv = 0; 676 int *ids; 677 678 sp = get_space(lsname); 679 if (!sp) 680 return -EEXIST; 681 682 mutex_lock(&sp->members_lock); 683 if (!sp->members_count) { 684 rv = 0; 685 goto out; 686 } 687 688 ids = kcalloc(sp->members_count, sizeof(int), GFP_KERNEL); 689 if (!ids) { 690 rv = -ENOMEM; 691 goto out; 692 } 693 694 rv = sp->members_count; 695 list_for_each_entry(nd, &sp->members, list) 696 ids[i++] = nd->nodeid; 697 698 if (rv != i) 699 printk("bad nodeid count %d %d\n", rv, i); 700 701 *ids_out = ids; 702 out: 703 mutex_unlock(&sp->members_lock); 704 put_space(sp); 705 return rv; 706} 707 708int dlm_node_weight(char *lsname, int nodeid) 709{ 710 struct space *sp; 711 struct node *nd; 712 int w = -EEXIST; 713 714 sp = get_space(lsname); 715 if (!sp) 716 goto out; 717 718 mutex_lock(&sp->members_lock); 719 list_for_each_entry(nd, &sp->members, list) { 720 if (nd->nodeid != nodeid) 721 continue; 722 w = nd->weight; 723 break; 724 } 725 mutex_unlock(&sp->members_lock); 726 put_space(sp); 727 out: 728 return w; 729} 730 731int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) 732{ 733 struct comm *cm = get_comm(nodeid, NULL); 734 if (!cm) 735 return -EEXIST; 736 if (!cm->addr_count) 737 return -ENOENT; 738 memcpy(addr, cm->addr[0], sizeof(*addr)); 739 put_comm(cm); 740 return 0; 741} 742 743int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) 744{ 745 struct comm *cm = get_comm(0, addr); 746 if (!cm) 747 return -EEXIST; 748 *nodeid = cm->nodeid; 749 put_comm(cm); 750 return 0; 751} 752 753int dlm_our_nodeid(void) 754{ 755 return local_comm ? local_comm->nodeid : 0; 756} 757 758/* num 0 is first addr, num 1 is second addr */ 759int dlm_our_addr(struct sockaddr_storage *addr, int num) 760{ 761 if (!local_comm) 762 return -1; 763 if (num + 1 > local_comm->addr_count) 764 return -1; 765 memcpy(addr, local_comm->addr[num], sizeof(*addr)); 766 return 0; 767} 768 769/* Config file defaults */ 770#define DEFAULT_TCP_PORT 21064 771#define DEFAULT_BUFFER_SIZE 4096 772#define DEFAULT_RSBTBL_SIZE 256 773#define DEFAULT_LKBTBL_SIZE 1024 774#define DEFAULT_DIRTBL_SIZE 512 775#define DEFAULT_RECOVER_TIMER 5 776#define DEFAULT_TOSS_SECS 10 777#define DEFAULT_SCAN_SECS 5 778 779struct dlm_config_info dlm_config = { 780 .tcp_port = DEFAULT_TCP_PORT, 781 .buffer_size = DEFAULT_BUFFER_SIZE, 782 .rsbtbl_size = DEFAULT_RSBTBL_SIZE, 783 .lkbtbl_size = DEFAULT_LKBTBL_SIZE, 784 .dirtbl_size = DEFAULT_DIRTBL_SIZE, 785 .recover_timer = DEFAULT_RECOVER_TIMER, 786 .toss_secs = DEFAULT_TOSS_SECS, 787 .scan_secs = DEFAULT_SCAN_SECS 788}; 789