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 *group,
 313                          int grouplen,
 314                          struct ocfs2_locking_protocol *lproto,
 315                          void (*recovery_handler)(int node_num,
 316                                                   void *recovery_data),
 317                          void *recovery_data,
 318                          struct ocfs2_cluster_connection **conn)
 319{
 320        int rc = 0;
 321        struct ocfs2_cluster_connection *new_conn;
 322
 323        BUG_ON(group == NULL);
 324        BUG_ON(conn == NULL);
 325        BUG_ON(recovery_handler == NULL);
 326
 327        if (grouplen > GROUP_NAME_MAX) {
 328                rc = -EINVAL;
 329                goto out;
 330        }
 331
 332        if (memcmp(&lproto->lp_max_version, &locking_max_version,
 333                   sizeof(struct ocfs2_protocol_version))) {
 334                rc = -EINVAL;
 335                goto out;
 336        }
 337
 338        new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection),
 339                           GFP_KERNEL);
 340        if (!new_conn) {
 341                rc = -ENOMEM;
 342                goto out;
 343        }
 344
 345        memcpy(new_conn->cc_name, group, grouplen);
 346        new_conn->cc_namelen = grouplen;
 347        new_conn->cc_recovery_handler = recovery_handler;
 348        new_conn->cc_recovery_data = recovery_data;
 349
 350        new_conn->cc_proto = lproto;
 351        /* Start the new connection at our maximum compatibility level */
 352        new_conn->cc_version = lproto->lp_max_version;
 353
 354        /* This will pin the stack driver if successful */
 355        rc = ocfs2_stack_driver_get(stack_name);
 356        if (rc)
 357                goto out_free;
 358
 359        rc = active_stack->sp_ops->connect(new_conn);
 360        if (rc) {
 361                ocfs2_stack_driver_put();
 362                goto out_free;
 363        }
 364
 365        *conn = new_conn;
 366
 367out_free:
 368        if (rc)
 369                kfree(new_conn);
 370
 371out:
 372        return rc;
 373}
 374EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
 375
 376/* The caller will ensure all nodes have the same cluster stack */
 377int ocfs2_cluster_connect_agnostic(const char *group,
 378                                   int grouplen,
 379                                   struct ocfs2_locking_protocol *lproto,
 380                                   void (*recovery_handler)(int node_num,
 381                                                            void *recovery_data),
 382                                   void *recovery_data,
 383                                   struct ocfs2_cluster_connection **conn)
 384{
 385        char *stack_name = NULL;
 386
 387        if (cluster_stack_name[0])
 388                stack_name = cluster_stack_name;
 389        return ocfs2_cluster_connect(stack_name, group, grouplen, lproto,
 390                                     recovery_handler, recovery_data, conn);
 391}
 392EXPORT_SYMBOL_GPL(ocfs2_cluster_connect_agnostic);
 393
 394/* If hangup_pending is 0, the stack driver will be dropped */
 395int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
 396                             int hangup_pending)
 397{
 398        int ret;
 399
 400        BUG_ON(conn == NULL);
 401
 402        ret = active_stack->sp_ops->disconnect(conn);
 403
 404        /* XXX Should we free it anyway? */
 405        if (!ret) {
 406                kfree(conn);
 407                if (!hangup_pending)
 408                        ocfs2_stack_driver_put();
 409        }
 410
 411        return ret;
 412}
 413EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect);
 414
 415/*
 416 * Leave the group for this filesystem.  This is executed by a userspace
 417 * program (stored in ocfs2_hb_ctl_path).
 418 */
 419static void ocfs2_leave_group(const char *group)
 420{
 421        int ret;
 422        char *argv[5], *envp[3];
 423
 424        argv[0] = ocfs2_hb_ctl_path;
 425        argv[1] = "-K";
 426        argv[2] = "-u";
 427        argv[3] = (char *)group;
 428        argv[4] = NULL;
 429
 430        /* minimal command environment taken from cpu_run_sbin_hotplug */
 431        envp[0] = "HOME=/";
 432        envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 433        envp[2] = NULL;
 434
 435        ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
 436        if (ret < 0) {
 437                printk(KERN_ERR
 438                       "ocfs2: Error %d running user helper "
 439                       "\"%s %s %s %s\"\n",
 440                       ret, argv[0], argv[1], argv[2], argv[3]);
 441        }
 442}
 443
 444/*
 445 * Hangup is a required post-umount.  ocfs2-tools software expects the
 446 * filesystem to call "ocfs2_hb_ctl" during unmount.  This happens
 447 * regardless of whether the DLM got started, so we can't do it
 448 * in ocfs2_cluster_disconnect().  The ocfs2_leave_group() function does
 449 * the actual work.
 450 */
 451void ocfs2_cluster_hangup(const char *group, int grouplen)
 452{
 453        BUG_ON(group == NULL);
 454        BUG_ON(group[grouplen] != '\0');
 455
 456        ocfs2_leave_group(group);
 457
 458        /* cluster_disconnect() was called with hangup_pending==1 */
 459        ocfs2_stack_driver_put();
 460}
 461EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
 462
 463int ocfs2_cluster_this_node(unsigned int *node)
 464{
 465        return active_stack->sp_ops->this_node(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_IFREG | 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_IFREG | 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_IFREG | 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_IFREG | S_IRUGO | S_IWUSR,
 595               ocfs2_cluster_stack_show,
 596               ocfs2_cluster_stack_store);
 597
 598static struct attribute *ocfs2_attrs[] = {
 599        &ocfs2_attr_max_locking_protocol.attr,
 600        &ocfs2_attr_loaded_cluster_plugins.attr,
 601        &ocfs2_attr_active_cluster_plugin.attr,
 602        &ocfs2_attr_cluster_stack.attr,
 603        NULL,
 604};
 605
 606static struct attribute_group ocfs2_attr_group = {
 607        .attrs = ocfs2_attrs,
 608};
 609
 610static struct kset *ocfs2_kset;
 611
 612static void ocfs2_sysfs_exit(void)
 613{
 614        kset_unregister(ocfs2_kset);
 615}
 616
 617static int ocfs2_sysfs_init(void)
 618{
 619        int ret;
 620
 621        ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj);
 622        if (!ocfs2_kset)
 623                return -ENOMEM;
 624
 625        ret = sysfs_create_group(&ocfs2_kset->kobj, &ocfs2_attr_group);
 626        if (ret)
 627                goto error;
 628
 629        return 0;
 630
 631error:
 632        kset_unregister(ocfs2_kset);
 633        return ret;
 634}
 635
 636/*
 637 * Sysctl bits
 638 *
 639 * The sysctl lives at /proc/sys/fs/ocfs2/nm/hb_ctl_path.  The 'nm' doesn't
 640 * make as much sense in a multiple cluster stack world, but it's safer
 641 * and easier to preserve the name.
 642 */
 643
 644#define FS_OCFS2_NM             1
 645
 646static ctl_table ocfs2_nm_table[] = {
 647        {
 648                .procname       = "hb_ctl_path",
 649                .data           = ocfs2_hb_ctl_path,
 650                .maxlen         = OCFS2_MAX_HB_CTL_PATH,
 651                .mode           = 0644,
 652                .proc_handler   = proc_dostring,
 653        },
 654        { }
 655};
 656
 657static ctl_table ocfs2_mod_table[] = {
 658        {
 659                .procname       = "nm",
 660                .data           = NULL,
 661                .maxlen         = 0,
 662                .mode           = 0555,
 663                .child          = ocfs2_nm_table
 664        },
 665        { }
 666};
 667
 668static ctl_table ocfs2_kern_table[] = {
 669        {
 670                .procname       = "ocfs2",
 671                .data           = NULL,
 672                .maxlen         = 0,
 673                .mode           = 0555,
 674                .child          = ocfs2_mod_table
 675        },
 676        { }
 677};
 678
 679static ctl_table ocfs2_root_table[] = {
 680        {
 681                .procname       = "fs",
 682                .data           = NULL,
 683                .maxlen         = 0,
 684                .mode           = 0555,
 685                .child          = ocfs2_kern_table
 686        },
 687        { }
 688};
 689
 690static struct ctl_table_header *ocfs2_table_header = NULL;
 691
 692
 693/*
 694 * Initialization
 695 */
 696
 697static int __init ocfs2_stack_glue_init(void)
 698{
 699        strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
 700
 701        ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
 702        if (!ocfs2_table_header) {
 703                printk(KERN_ERR
 704                       "ocfs2 stack glue: unable to register sysctl\n");
 705                return -ENOMEM; /* or something. */
 706        }
 707
 708        return ocfs2_sysfs_init();
 709}
 710
 711static void __exit ocfs2_stack_glue_exit(void)
 712{
 713        memset(&locking_max_version, 0,
 714               sizeof(struct ocfs2_protocol_version));
 715        locking_max_version.pv_major = 0;
 716        locking_max_version.pv_minor = 0;
 717        ocfs2_sysfs_exit();
 718        if (ocfs2_table_header)
 719                unregister_sysctl_table(ocfs2_table_header);
 720}
 721
 722MODULE_AUTHOR("Oracle");
 723MODULE_DESCRIPTION("ocfs2 cluter stack glue layer");
 724MODULE_LICENSE("GPL");
 725module_init(ocfs2_stack_glue_init);
 726module_exit(ocfs2_stack_glue_exit);
 727
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.