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