linux/fs/ocfs2/stackglue.c
<<
>>
Prefs
   1/* -*- mode: c; c-basic-offset: 8; -*-
   2 * vim: noexpandtab sw=8 ts=8 sts=0:
   3 *
   4 * stackglue.c
   5 *
   6 * Code which implements an OCFS2 specific interface to underlying
   7 * cluster stacks.
   8 *
   9 * Copyright (C) 2007, 2009 Oracle.  All rights reserved.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public
  13 * License as published by the Free Software Foundation, version 2.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 * General Public License for more details.
  19 */
  20
  21#include <linux/list.h>
  22#include <linux/spinlock.h>
  23#include <linux/module.h>
  24#include <linux/slab.h>
  25#include <linux/kmod.h>
  26#include <linux/fs.h>
  27#include <linux/kobject.h>
  28#include <linux/sysfs.h>
  29#include <linux/sysctl.h>
  30
  31#include "ocfs2_fs.h"
  32
  33#include "stackglue.h"
  34
  35#define OCFS2_STACK_PLUGIN_O2CB         "o2cb"
  36#define OCFS2_STACK_PLUGIN_USER         "user"
  37#define OCFS2_MAX_HB_CTL_PATH           256
  38
  39static struct ocfs2_protocol_version locking_max_version;
  40static DEFINE_SPINLOCK(ocfs2_stack_lock);
  41static LIST_HEAD(ocfs2_stack_list);
  42static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1];
  43static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";
  44
  45/*
  46 * The stack currently in use.  If not null, active_stack->sp_count > 0,
  47 * the module is pinned, and the locking protocol cannot be changed.
  48 */
  49static struct ocfs2_stack_plugin *active_stack;
  50
  51static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
  52{
  53        struct ocfs2_stack_plugin *p;
  54
  55        assert_spin_locked(&ocfs2_stack_lock);
  56
  57        list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
  58                if (!strcmp(p->sp_name, name))
  59                        return p;
  60        }
  61
  62        return NULL;
  63}
  64
  65static int ocfs2_stack_driver_request(const char *stack_name,
  66                                      const char *plugin_name)
  67{
  68        int rc;
  69        struct ocfs2_stack_plugin *p;
  70
  71        spin_lock(&ocfs2_stack_lock);
  72
  73        /*
  74         * If the stack passed by the filesystem isn't the selected one,
  75         * we can't continue.
  76         */
  77        if (strcmp(stack_name, cluster_stack_name)) {
  78                rc = -EBUSY;
  79                goto out;
  80        }
  81
  82        if (active_stack) {
  83                /*
  84                 * If the active stack isn't the one we want, it cannot
  85                 * be selected right now.
  86                 */
  87                if (!strcmp(active_stack->sp_name, plugin_name))
  88                        rc = 0;
  89                else
  90                        rc = -EBUSY;
  91                goto out;
  92        }
  93
  94        p = ocfs2_stack_lookup(plugin_name);
  95        if (!p || !try_module_get(p->sp_owner)) {
  96                rc = -ENOENT;
  97                goto out;
  98        }
  99
 100        active_stack = p;
 101        rc = 0;
 102
 103out:
 104        /* If we found it, pin it */
 105        if (!rc)
 106                active_stack->sp_count++;
 107
 108        spin_unlock(&ocfs2_stack_lock);
 109        return rc;
 110}
 111
 112/*
 113 * This function looks up the appropriate stack and makes it active.  If
 114 * there is no stack, it tries to load it.  It will fail if the stack still
 115 * cannot be found.  It will also fail if a different stack is in use.
 116 */
 117static int ocfs2_stack_driver_get(const char *stack_name)
 118{
 119        int rc;
 120        char *plugin_name = OCFS2_STACK_PLUGIN_O2CB;
 121
 122        /*
 123         * Classic stack does not pass in a stack name.  This is
 124         * compatible with older tools as well.
 125         */
 126        if (!stack_name || !*stack_name)
 127                stack_name = OCFS2_STACK_PLUGIN_O2CB;
 128
 129        if (strlen(stack_name) != OCFS2_STACK_LABEL_LEN) {
 130                printk(KERN_ERR
 131                       "ocfs2 passed an invalid cluster stack label: \"%s\"\n",
 132                       stack_name);
 133                return -EINVAL;
 134        }
 135
 136        /* Anything that isn't the classic stack is a user stack */
 137        if (strcmp(stack_name, OCFS2_STACK_PLUGIN_O2CB))
 138                plugin_name = OCFS2_STACK_PLUGIN_USER;
 139
 140        rc = ocfs2_stack_driver_request(stack_name, plugin_name);
 141        if (rc == -ENOENT) {
 142                request_module("ocfs2_stack_%s", plugin_name);
 143                rc = ocfs2_stack_driver_request(stack_name, plugin_name);
 144        }
 145
 146        if (rc == -ENOENT) {
 147                printk(KERN_ERR
 148                       "ocfs2: Cluster stack driver \"%s\" cannot be found\n",
 149                       plugin_name);
 150        } else if (rc == -EBUSY) {
 151                printk(KERN_ERR
 152                       "ocfs2: A different cluster stack is in use\n");
 153        }
 154
 155        return rc;
 156}
 157
 158static void ocfs2_stack_driver_put(void)
 159{
 160        spin_lock(&ocfs2_stack_lock);
 161        BUG_ON(active_stack == NULL);
 162        BUG_ON(active_stack->sp_count == 0);
 163
 164        active_stack->sp_count--;
 165        if (!active_stack->sp_count) {
 166                module_put(active_stack->sp_owner);
 167                active_stack = NULL;
 168        }
 169        spin_unlock(&ocfs2_stack_lock);
 170}
 171
 172int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin)
 173{
 174        int rc;
 175
 176        spin_lock(&ocfs2_stack_lock);
 177        if (!ocfs2_stack_lookup(plugin->sp_name)) {
 178                plugin->sp_count = 0;
 179                plugin->sp_max_proto = locking_max_version;
 180                list_add(&plugin->sp_list, &ocfs2_stack_list);
 181                printk(KERN_INFO "ocfs2: Registered cluster interface %s\n",
 182                       plugin->sp_name);
 183                rc = 0;
 184        } else {
 185                printk(KERN_ERR "ocfs2: Stack \"%s\" already registered\n",
 186                       plugin->sp_name);
 187                rc = -EEXIST;
 188        }
 189        spin_unlock(&ocfs2_stack_lock);
 190
 191        return rc;
 192}
 193EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register);
 194
 195void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin)
 196{
 197        struct ocfs2_stack_plugin *p;
 198
 199        spin_lock(&ocfs2_stack_lock);
 200        p = ocfs2_stack_lookup(plugin->sp_name);
 201        if (p) {
 202                BUG_ON(p != plugin);
 203                BUG_ON(plugin == active_stack);
 204                BUG_ON(plugin->sp_count != 0);
 205                list_del_init(&plugin->sp_list);
 206                printk(KERN_INFO "ocfs2: Unregistered cluster interface %s\n",
 207                       plugin->sp_name);
 208        } else {
 209                printk(KERN_ERR "Stack \"%s\" is not registered\n",
 210                       plugin->sp_name);
 211        }
 212        spin_unlock(&ocfs2_stack_lock);
 213}
 214EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister);
 215
 216void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_proto)
 217{
 218        struct ocfs2_stack_plugin *p;
 219
 220        spin_lock(&ocfs2_stack_lock);
 221        if (memcmp(max_proto, &locking_max_version,
 222                   sizeof(struct ocfs2_protocol_version))) {
 223                BUG_ON(locking_max_version.pv_major != 0);
 224
 225                locking_max_version = *max_proto;
 226                list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
 227                        p->sp_max_proto = locking_max_version;
 228                }
 229        }
 230        spin_unlock(&ocfs2_stack_lock);
 231}
 232EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_max_proto_version);
 233
 234
 235/*
 236 * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take no argument
 237 * for the ast and bast functions.  They will pass the lksb to the ast
 238 * and bast.  The caller can wrap the lksb with their own structure to
 239 * get more information.
 240 */
 241int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
 242                   int mode,
 243                   struct ocfs2_dlm_lksb *lksb,
 244                   u32 flags,
 245                   void *name,
 246                   unsigned int namelen)
 247{
 248        if (!lksb->lksb_conn)
 249                lksb->lksb_conn = conn;
 250        else
 251                BUG_ON(lksb->lksb_conn != conn);
 252        return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
 253                                              name, namelen);
 254}
 255EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
 256
 257int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
 258                     struct ocfs2_dlm_lksb *lksb,
 259                     u32 flags)
 260{
 261        BUG_ON(lksb->lksb_conn == NULL);
 262
 263        return active_stack->sp_ops->dlm_unlock(conn, lksb, flags);
 264}
 265EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock);
 266
 267int ocfs2_dlm_lock_status(struct ocfs2_dlm_lksb *lksb)
 268{
 269        return active_stack->sp_ops->lock_status(lksb);
 270}
 271EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status);
 272
 273int ocfs2_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb)
 274{
 275        return active_stack->sp_ops->lvb_valid(lksb);
 276}
 277EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb_valid);
 278
 279void *ocfs2_dlm_lvb(struct ocfs2_dlm_lksb *lksb)
 280{
 281        return active_stack->sp_ops->lock_lvb(lksb);
 282}
 283EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb);
 284
 285void ocfs2_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb)
 286{
 287        active_stack->sp_ops->dump_lksb(lksb);
 288}
 289EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
 290
 291int ocfs2_stack_supports_plocks(void)
 292{
 293        return active_stack && active_stack->sp_ops->plock;
 294}
 295EXPORT_SYMBOL_GPL(ocfs2_stack_supports_plocks);
 296
 297/*
 298 * ocfs2_plock() can only be safely called if
 299 * ocfs2_stack_supports_plocks() returned true
 300 */
 301int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
 302                struct file *file, int cmd, struct file_lock *fl)
 303{
 304        WARN_ON_ONCE(active_stack->sp_ops->plock == NULL);
 305        if (active_stack->sp_ops->plock)
 306                return active_stack->sp_ops->plock(conn, ino, file, cmd, fl);
 307        return -EOPNOTSUPP;
 308}
 309EXPORT_SYMBOL_GPL(ocfs2_plock);
 310
 311int ocfs2_cluster_connect(const char *stack_name,
 312                          const char *cluster_name,
 313                          int cluster_name_len,
 314                          const char *group,
 315                          int grouplen,
 316                          struct ocfs2_locking_protocol *lproto,
 317                          void (*recovery_handler)(int node_num,
 318                                                   void *recovery_data),
 319                          void *recovery_data,
 320                          struct ocfs2_cluster_connection **conn)
 321{
 322        int rc = 0;
 323        struct ocfs2_cluster_connection *new_conn;
 324
 325        BUG_ON(group == NULL);
 326        BUG_ON(conn == NULL);
 327        BUG_ON(recovery_handler == NULL);
 328
 329        if (grouplen > GROUP_NAME_MAX) {
 330                rc = -EINVAL;
 331                goto out;
 332        }
 333
 334        if (memcmp(&lproto->lp_max_version, &locking_max_version,
 335                   sizeof(struct ocfs2_protocol_version))) {
 336                rc = -EINVAL;
 337                goto out;
 338        }
 339
 340        new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection),
 341                           GFP_KERNEL);
 342        if (!new_conn) {
 343                rc = -ENOMEM;
 344                goto out;
 345        }
 346
 347        strlcpy(new_conn->cc_name, group, GROUP_NAME_MAX + 1);
 348        new_conn->cc_namelen = grouplen;
 349        if (cluster_name_len)
 350                strlcpy(new_conn->cc_cluster_name, cluster_name,
 351                        CLUSTER_NAME_MAX + 1);
 352        new_conn->cc_cluster_name_len = cluster_name_len;
 353        new_conn->cc_recovery_handler = recovery_handler;
 354        new_conn->cc_recovery_data = recovery_data;
 355
 356        new_conn->cc_proto = lproto;
 357        /* Start the new connection at our maximum compatibility level */
 358        new_conn->cc_version = lproto->lp_max_version;
 359
 360        /* This will pin the stack driver if successful */
 361        rc = ocfs2_stack_driver_get(stack_name);
 362        if (rc)
 363                goto out_free;
 364
 365        rc = active_stack->sp_ops->connect(new_conn);
 366        if (rc) {
 367                ocfs2_stack_driver_put();
 368                goto out_free;
 369        }
 370
 371        *conn = new_conn;
 372
 373out_free:
 374        if (rc)
 375                kfree(new_conn);
 376
 377out:
 378        return rc;
 379}
 380EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
 381
 382/* The caller will ensure all nodes have the same cluster stack */
 383int ocfs2_cluster_connect_agnostic(const char *group,
 384                                   int grouplen,
 385                                   struct ocfs2_locking_protocol *lproto,
 386                                   void (*recovery_handler)(int node_num,
 387                                                            void *recovery_data),
 388                                   void *recovery_data,
 389                                   struct ocfs2_cluster_connection **conn)
 390{
 391        char *stack_name = NULL;
 392
 393        if (cluster_stack_name[0])
 394                stack_name = cluster_stack_name;
 395        return ocfs2_cluster_connect(stack_name, NULL, 0, group, grouplen,
 396                                     lproto, recovery_handler, recovery_data,
 397                                     conn);
 398}
 399EXPORT_SYMBOL_GPL(ocfs2_cluster_connect_agnostic);
 400
 401/* If hangup_pending is 0, the stack driver will be dropped */
 402int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
 403                             int hangup_pending)
 404{
 405        int ret;
 406
 407        BUG_ON(conn == NULL);
 408
 409        ret = active_stack->sp_ops->disconnect(conn);
 410
 411        /* XXX Should we free it anyway? */
 412        if (!ret) {
 413                kfree(conn);
 414                if (!hangup_pending)
 415                        ocfs2_stack_driver_put();
 416        }
 417
 418        return ret;
 419}
 420EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect);
 421
 422/*
 423 * Leave the group for this filesystem.  This is executed by a userspace
 424 * program (stored in ocfs2_hb_ctl_path).
 425 */
 426static void ocfs2_leave_group(const char *group)
 427{
 428        int ret;
 429        char *argv[5], *envp[3];
 430
 431        argv[0] = ocfs2_hb_ctl_path;
 432        argv[1] = "-K";
 433        argv[2] = "-u";
 434        argv[3] = (char *)group;
 435        argv[4] = NULL;
 436
 437        /* minimal command environment taken from cpu_run_sbin_hotplug */
 438        envp[0] = "HOME=/";
 439        envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 440        envp[2] = NULL;
 441
 442        ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
 443        if (ret < 0) {
 444                printk(KERN_ERR
 445                       "ocfs2: Error %d running user helper "
 446                       "\"%s %s %s %s\"\n",
 447                       ret, argv[0], argv[1], argv[2], argv[3]);
 448        }
 449}
 450
 451/*
 452 * Hangup is a required post-umount.  ocfs2-tools software expects the
 453 * filesystem to call "ocfs2_hb_ctl" during unmount.  This happens
 454 * regardless of whether the DLM got started, so we can't do it
 455 * in ocfs2_cluster_disconnect().  The ocfs2_leave_group() function does
 456 * the actual work.
 457 */
 458void ocfs2_cluster_hangup(const char *group, int grouplen)
 459{
 460        BUG_ON(group == NULL);
 461        BUG_ON(group[grouplen] != '\0');
 462
 463        ocfs2_leave_group(group);
 464
 465        /* cluster_disconnect() was called with hangup_pending==1 */
 466        ocfs2_stack_driver_put();
 467}
 468EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
 469
 470int ocfs2_cluster_this_node(struct ocfs2_cluster_connection *conn,
 471                            unsigned int *node)
 472{
 473        return active_stack->sp_ops->this_node(conn, node);
 474}
 475EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node);
 476
 477
 478/*
 479 * Sysfs bits
 480 */
 481
 482static ssize_t ocfs2_max_locking_protocol_show(struct kobject *kobj,
 483                                               struct kobj_attribute *attr,
 484                                               char *buf)
 485{
 486        ssize_t ret = 0;
 487
 488        spin_lock(&ocfs2_stack_lock);
 489        if (locking_max_version.pv_major)
 490                ret = snprintf(buf, PAGE_SIZE, "%u.%u\n",
 491                               locking_max_version.pv_major,
 492                               locking_max_version.pv_minor);
 493        spin_unlock(&ocfs2_stack_lock);
 494
 495        return ret;
 496}
 497
 498static struct kobj_attribute ocfs2_attr_max_locking_protocol =
 499        __ATTR(max_locking_protocol, S_IRUGO,
 500               ocfs2_max_locking_protocol_show, NULL);
 501
 502static ssize_t ocfs2_loaded_cluster_plugins_show(struct kobject *kobj,
 503                                                 struct kobj_attribute *attr,
 504                                                 char *buf)
 505{
 506        ssize_t ret = 0, total = 0, remain = PAGE_SIZE;
 507        struct ocfs2_stack_plugin *p;
 508
 509        spin_lock(&ocfs2_stack_lock);
 510        list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
 511                ret = snprintf(buf, remain, "%s\n",
 512                               p->sp_name);
 513                if (ret < 0) {
 514                        total = ret;
 515                        break;
 516                }
 517                if (ret == remain) {
 518                        /* snprintf() didn't fit */
 519                        total = -E2BIG;
 520                        break;
 521                }
 522                total += ret;
 523                remain -= ret;
 524        }
 525        spin_unlock(&ocfs2_stack_lock);
 526
 527        return total;
 528}
 529
 530static struct kobj_attribute ocfs2_attr_loaded_cluster_plugins =
 531        __ATTR(loaded_cluster_plugins, S_IRUGO,
 532               ocfs2_loaded_cluster_plugins_show, NULL);
 533
 534static ssize_t ocfs2_active_cluster_plugin_show(struct kobject *kobj,
 535                                                struct kobj_attribute *attr,
 536                                                char *buf)
 537{
 538        ssize_t ret = 0;
 539
 540        spin_lock(&ocfs2_stack_lock);
 541        if (active_stack) {
 542                ret = snprintf(buf, PAGE_SIZE, "%s\n",
 543                               active_stack->sp_name);
 544                if (ret == PAGE_SIZE)
 545                        ret = -E2BIG;
 546        }
 547        spin_unlock(&ocfs2_stack_lock);
 548
 549        return ret;
 550}
 551
 552static struct kobj_attribute ocfs2_attr_active_cluster_plugin =
 553        __ATTR(active_cluster_plugin, S_IRUGO,
 554               ocfs2_active_cluster_plugin_show, NULL);
 555
 556static ssize_t ocfs2_cluster_stack_show(struct kobject *kobj,
 557                                        struct kobj_attribute *attr,
 558                                        char *buf)
 559{
 560        ssize_t ret;
 561        spin_lock(&ocfs2_stack_lock);
 562        ret = snprintf(buf, PAGE_SIZE, "%s\n", cluster_stack_name);
 563        spin_unlock(&ocfs2_stack_lock);
 564
 565        return ret;
 566}
 567
 568static ssize_t ocfs2_cluster_stack_store(struct kobject *kobj,
 569                                         struct kobj_attribute *attr,
 570                                         const char *buf, size_t count)
 571{
 572        size_t len = count;
 573        ssize_t ret;
 574
 575        if (len == 0)
 576                return len;
 577
 578        if (buf[len - 1] == '\n')
 579                len--;
 580
 581        if ((len != OCFS2_STACK_LABEL_LEN) ||
 582            (strnlen(buf, len) != len))
 583                return -EINVAL;
 584
 585        spin_lock(&ocfs2_stack_lock);
 586        if (active_stack) {
 587                if (!strncmp(buf, cluster_stack_name, len))
 588                        ret = count;
 589                else
 590                        ret = -EBUSY;
 591        } else {
 592                memcpy(cluster_stack_name, buf, len);
 593                ret = count;
 594        }
 595        spin_unlock(&ocfs2_stack_lock);
 596
 597        return ret;
 598}
 599
 600
 601static struct kobj_attribute ocfs2_attr_cluster_stack =
 602        __ATTR(cluster_stack, S_IRUGO | S_IWUSR,
 603               ocfs2_cluster_stack_show,
 604               ocfs2_cluster_stack_store);
 605
 606
 607
 608static ssize_t ocfs2_dlm_recover_show(struct kobject *kobj,
 609                                        struct kobj_attribute *attr,
 610                                        char *buf)
 611{
 612        return snprintf(buf, PAGE_SIZE, "1\n");
 613}
 614
 615static struct kobj_attribute ocfs2_attr_dlm_recover_support =
 616        __ATTR(dlm_recover_callback_support, S_IRUGO,
 617               ocfs2_dlm_recover_show, NULL);
 618
 619static struct attribute *ocfs2_attrs[] = {
 620        &ocfs2_attr_max_locking_protocol.attr,
 621        &ocfs2_attr_loaded_cluster_plugins.attr,
 622        &ocfs2_attr_active_cluster_plugin.attr,
 623        &ocfs2_attr_cluster_stack.attr,
 624        &ocfs2_attr_dlm_recover_support.attr,
 625        NULL,
 626};
 627
 628static struct attribute_group ocfs2_attr_group = {
 629        .attrs = ocfs2_attrs,
 630};
 631
 632static struct kset *ocfs2_kset;
 633
 634static void ocfs2_sysfs_exit(void)
 635{
 636        kset_unregister(ocfs2_kset);
 637}
 638
 639static int ocfs2_sysfs_init(void)
 640{
 641        int ret;
 642
 643        ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj);
 644        if (!ocfs2_kset)
 645                return -ENOMEM;
 646
 647        ret = sysfs_create_group(&ocfs2_kset->kobj, &ocfs2_attr_group);
 648        if (ret)
 649                goto error;
 650
 651        return 0;
 652
 653error:
 654        kset_unregister(ocfs2_kset);
 655        return ret;
 656}
 657
 658/*
 659 * Sysctl bits
 660 *
 661 * The sysctl lives at /proc/sys/fs/ocfs2/nm/hb_ctl_path.  The 'nm' doesn't
 662 * make as much sense in a multiple cluster stack world, but it's safer
 663 * and easier to preserve the name.
 664 */
 665
 666#define FS_OCFS2_NM             1
 667
 668static struct ctl_table ocfs2_nm_table[] = {
 669        {
 670                .procname       = "hb_ctl_path",
 671                .data           = ocfs2_hb_ctl_path,
 672                .maxlen         = OCFS2_MAX_HB_CTL_PATH,
 673                .mode           = 0644,
 674                .proc_handler   = proc_dostring,
 675        },
 676        { }
 677};
 678
 679static struct ctl_table ocfs2_mod_table[] = {
 680        {
 681                .procname       = "nm",
 682                .data           = NULL,
 683                .maxlen         = 0,
 684                .mode           = 0555,
 685                .child          = ocfs2_nm_table
 686        },
 687        { }
 688};
 689
 690static struct ctl_table ocfs2_kern_table[] = {
 691        {
 692                .procname       = "ocfs2",
 693                .data           = NULL,
 694                .maxlen         = 0,
 695                .mode           = 0555,
 696                .child          = ocfs2_mod_table
 697        },
 698        { }
 699};
 700
 701static struct ctl_table ocfs2_root_table[] = {
 702        {
 703                .procname       = "fs",
 704                .data           = NULL,
 705                .maxlen         = 0,
 706                .mode           = 0555,
 707                .child          = ocfs2_kern_table
 708        },
 709        { }
 710};
 711
 712static struct ctl_table_header *ocfs2_table_header;
 713
 714
 715/*
 716 * Initialization
 717 */
 718
 719static int __init ocfs2_stack_glue_init(void)
 720{
 721        strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
 722
 723        ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
 724        if (!ocfs2_table_header) {
 725                printk(KERN_ERR
 726                       "ocfs2 stack glue: unable to register sysctl\n");
 727                return -ENOMEM; /* or something. */
 728        }
 729
 730        return ocfs2_sysfs_init();
 731}
 732
 733static void __exit ocfs2_stack_glue_exit(void)
 734{
 735        memset(&locking_max_version, 0,
 736               sizeof(struct ocfs2_protocol_version));
 737        locking_max_version.pv_major = 0;
 738        locking_max_version.pv_minor = 0;
 739        ocfs2_sysfs_exit();
 740        if (ocfs2_table_header)
 741                unregister_sysctl_table(ocfs2_table_header);
 742}
 743
 744MODULE_AUTHOR("Oracle");
 745MODULE_DESCRIPTION("ocfs2 cluter stack glue layer");
 746MODULE_LICENSE("GPL");
 747module_init(ocfs2_stack_glue_init);
 748module_exit(ocfs2_stack_glue_exit);
 749