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