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