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