cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stackglue.c (16790B)


      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_header *ocfs2_table_header;
    665
    666/*
    667 * Initialization
    668 */
    669
    670static int __init ocfs2_stack_glue_init(void)
    671{
    672	strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
    673
    674	ocfs2_table_header = register_sysctl("fs/ocfs2/nm", ocfs2_nm_table);
    675	if (!ocfs2_table_header) {
    676		printk(KERN_ERR
    677		       "ocfs2 stack glue: unable to register sysctl\n");
    678		return -ENOMEM; /* or something. */
    679	}
    680
    681	return ocfs2_sysfs_init();
    682}
    683
    684static void __exit ocfs2_stack_glue_exit(void)
    685{
    686	memset(&locking_max_version, 0,
    687	       sizeof(struct ocfs2_protocol_version));
    688	ocfs2_sysfs_exit();
    689	if (ocfs2_table_header)
    690		unregister_sysctl_table(ocfs2_table_header);
    691}
    692
    693MODULE_AUTHOR("Oracle");
    694MODULE_DESCRIPTION("ocfs2 cluster stack glue layer");
    695MODULE_LICENSE("GPL");
    696module_init(ocfs2_stack_glue_init);
    697module_exit(ocfs2_stack_glue_exit);