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 31 static struct ocfs2_protocol_version locking_max_version; 32 static DEFINE_SPINLOCK(ocfs2_stack_lock); 33 static LIST_HEAD(ocfs2_stack_list); 34 static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1]; 35 static 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 */ 41 static struct ocfs2_stack_plugin *active_stack; 42 43 static 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 57 static 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 95 out: 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 */ 109 static 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 150 static 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 164 int 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 } 185 EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register); 186 187 void 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 } 206 EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister); 207 208 void 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 } 224 EXPORT_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 */ 233 int 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 } 247 EXPORT_SYMBOL_GPL(ocfs2_dlm_lock); 248 249 int 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 } 257 EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock); 258 259 int ocfs2_dlm_lock_status(struct ocfs2_dlm_lksb *lksb) 260 { 261 return active_stack->sp_ops->lock_status(lksb); 262 } 263 EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status); 264 265 int ocfs2_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb) 266 { 267 return active_stack->sp_ops->lvb_valid(lksb); 268 } 269 EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb_valid); 270 271 void *ocfs2_dlm_lvb(struct ocfs2_dlm_lksb *lksb) 272 { 273 return active_stack->sp_ops->lock_lvb(lksb); 274 } 275 EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb); 276 277 void ocfs2_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb) 278 { 279 active_stack->sp_ops->dump_lksb(lksb); 280 } 281 EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb); 282 283 int ocfs2_stack_supports_plocks(void) 284 { 285 return active_stack && active_stack->sp_ops->plock; 286 } 287 EXPORT_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 */ 293 int 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 } 301 EXPORT_SYMBOL_GPL(ocfs2_plock); 302 303 int 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 365 out_free: 366 if (rc) 367 kfree(new_conn); 368 369 out: 370 return rc; 371 } 372 EXPORT_SYMBOL_GPL(ocfs2_cluster_connect); 373 374 /* The caller will ensure all nodes have the same cluster stack */ 375 int 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 } 391 EXPORT_SYMBOL_GPL(ocfs2_cluster_connect_agnostic); 392 393 /* If hangup_pending is 0, the stack driver will be dropped */ 394 int 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 } 412 EXPORT_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 */ 418 static 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 */ 450 void 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 } 460 EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup); 461 462 int 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 } 467 EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node); 468 469 470 /* 471 * Sysfs bits 472 */ 473 474 static 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 490 static struct kobj_attribute ocfs2_attr_max_locking_protocol = 491 __ATTR(max_locking_protocol, S_IRUGO, 492 ocfs2_max_locking_protocol_show, NULL); 493 494 static 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 522 static struct kobj_attribute ocfs2_attr_loaded_cluster_plugins = 523 __ATTR(loaded_cluster_plugins, S_IRUGO, 524 ocfs2_loaded_cluster_plugins_show, NULL); 525 526 static 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 544 static struct kobj_attribute ocfs2_attr_active_cluster_plugin = 545 __ATTR(active_cluster_plugin, S_IRUGO, 546 ocfs2_active_cluster_plugin_show, NULL); 547 548 static 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 560 static 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 593 static 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 600 static 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 607 static struct kobj_attribute ocfs2_attr_dlm_recover_support = 608 __ATTR(dlm_recover_callback_support, S_IRUGO, 609 ocfs2_dlm_recover_show, NULL); 610 611 static 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 620 static const struct attribute_group ocfs2_attr_group = { 621 .attrs = ocfs2_attrs, 622 }; 623 624 struct kset *ocfs2_kset; 625 EXPORT_SYMBOL_GPL(ocfs2_kset); 626 627 static void ocfs2_sysfs_exit(void) 628 { 629 kset_unregister(ocfs2_kset); 630 } 631 632 static 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 646 error: 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 661 static 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 672 static 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 683 static 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 694 static 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 705 static struct ctl_table_header *ocfs2_table_header; 706 707 708 /* 709 * Initialization 710 */ 711 712 static 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 726 static 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 735 MODULE_AUTHOR("Oracle"); 736 MODULE_DESCRIPTION("ocfs2 cluter stack glue layer"); 737 MODULE_LICENSE("GPL"); 738 module_init(ocfs2_stack_glue_init); 739 module_exit(ocfs2_stack_glue_exit); 740