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