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