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