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