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