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