diff options
Diffstat (limited to 'fs/ocfs2/stackglue.c')
| -rw-r--r-- | fs/ocfs2/stackglue.c | 119 |
1 files changed, 116 insertions, 3 deletions
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 119f60cea9cc..10e149ae5e3a 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
| 27 | #include <linux/kobject.h> | 27 | #include <linux/kobject.h> |
| 28 | #include <linux/sysfs.h> | 28 | #include <linux/sysfs.h> |
| 29 | #include <linux/sysctl.h> | ||
| 29 | 30 | ||
| 30 | #include "ocfs2_fs.h" | 31 | #include "ocfs2_fs.h" |
| 31 | 32 | ||
| @@ -33,11 +34,13 @@ | |||
| 33 | 34 | ||
| 34 | #define OCFS2_STACK_PLUGIN_O2CB "o2cb" | 35 | #define OCFS2_STACK_PLUGIN_O2CB "o2cb" |
| 35 | #define OCFS2_STACK_PLUGIN_USER "user" | 36 | #define OCFS2_STACK_PLUGIN_USER "user" |
| 37 | #define OCFS2_MAX_HB_CTL_PATH 256 | ||
| 36 | 38 | ||
| 37 | static struct ocfs2_locking_protocol *lproto; | 39 | static struct ocfs2_locking_protocol *lproto; |
| 38 | static DEFINE_SPINLOCK(ocfs2_stack_lock); | 40 | static DEFINE_SPINLOCK(ocfs2_stack_lock); |
| 39 | static LIST_HEAD(ocfs2_stack_list); | 41 | static LIST_HEAD(ocfs2_stack_list); |
| 40 | static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1]; | 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"; | ||
| 41 | 44 | ||
| 42 | /* | 45 | /* |
| 43 | * The stack currently in use. If not null, active_stack->sp_count > 0, | 46 | * The stack currently in use. If not null, active_stack->sp_count > 0, |
| @@ -349,7 +352,7 @@ int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn, | |||
| 349 | 352 | ||
| 350 | BUG_ON(conn == NULL); | 353 | BUG_ON(conn == NULL); |
| 351 | 354 | ||
| 352 | ret = active_stack->sp_ops->disconnect(conn, hangup_pending); | 355 | ret = active_stack->sp_ops->disconnect(conn); |
| 353 | 356 | ||
| 354 | /* XXX Should we free it anyway? */ | 357 | /* XXX Should we free it anyway? */ |
| 355 | if (!ret) { | 358 | if (!ret) { |
| @@ -362,13 +365,48 @@ int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn, | |||
| 362 | } | 365 | } |
| 363 | EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect); | 366 | EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect); |
| 364 | 367 | ||
| 368 | /* | ||
| 369 | * Leave the group for this filesystem. This is executed by a userspace | ||
| 370 | * program (stored in ocfs2_hb_ctl_path). | ||
| 371 | */ | ||
| 372 | static void ocfs2_leave_group(const char *group) | ||
| 373 | { | ||
| 374 | int ret; | ||
| 375 | char *argv[5], *envp[3]; | ||
| 376 | |||
| 377 | argv[0] = ocfs2_hb_ctl_path; | ||
| 378 | argv[1] = "-K"; | ||
| 379 | argv[2] = "-u"; | ||
| 380 | argv[3] = (char *)group; | ||
| 381 | argv[4] = NULL; | ||
| 382 | |||
| 383 | /* minimal command environment taken from cpu_run_sbin_hotplug */ | ||
| 384 | envp[0] = "HOME=/"; | ||
| 385 | envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; | ||
| 386 | envp[2] = NULL; | ||
| 387 | |||
| 388 | ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); | ||
| 389 | if (ret < 0) { | ||
| 390 | printk(KERN_ERR | ||
| 391 | "ocfs2: Error %d running user helper " | ||
| 392 | "\"%s %s %s %s\"\n", | ||
| 393 | ret, argv[0], argv[1], argv[2], argv[3]); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 397 | /* | ||
| 398 | * Hangup is a required post-umount. ocfs2-tools software expects the | ||
| 399 | * filesystem to call "ocfs2_hb_ctl" during unmount. This happens | ||
| 400 | * regardless of whether the DLM got started, so we can't do it | ||
| 401 | * in ocfs2_cluster_disconnect(). The ocfs2_leave_group() function does | ||
| 402 | * the actual work. | ||
| 403 | */ | ||
| 365 | void ocfs2_cluster_hangup(const char *group, int grouplen) | 404 | void ocfs2_cluster_hangup(const char *group, int grouplen) |
| 366 | { | 405 | { |
| 367 | BUG_ON(group == NULL); | 406 | BUG_ON(group == NULL); |
| 368 | BUG_ON(group[grouplen] != '\0'); | 407 | BUG_ON(group[grouplen] != '\0'); |
| 369 | 408 | ||
| 370 | if (active_stack->sp_ops->hangup) | 409 | ocfs2_leave_group(group); |
| 371 | active_stack->sp_ops->hangup(group, grouplen); | ||
| 372 | 410 | ||
| 373 | /* cluster_disconnect() was called with hangup_pending==1 */ | 411 | /* cluster_disconnect() was called with hangup_pending==1 */ |
| 374 | ocfs2_stack_driver_put(); | 412 | ocfs2_stack_driver_put(); |
| @@ -548,10 +586,83 @@ error: | |||
| 548 | return ret; | 586 | return ret; |
| 549 | } | 587 | } |
| 550 | 588 | ||
| 589 | /* | ||
| 590 | * Sysctl bits | ||
| 591 | * | ||
| 592 | * The sysctl lives at /proc/sys/fs/ocfs2/nm/hb_ctl_path. The 'nm' doesn't | ||
| 593 | * make as much sense in a multiple cluster stack world, but it's safer | ||
| 594 | * and easier to preserve the name. | ||
| 595 | */ | ||
| 596 | |||
| 597 | #define FS_OCFS2_NM 1 | ||
| 598 | |||
| 599 | static ctl_table ocfs2_nm_table[] = { | ||
| 600 | { | ||
| 601 | .ctl_name = 1, | ||
| 602 | .procname = "hb_ctl_path", | ||
| 603 | .data = ocfs2_hb_ctl_path, | ||
| 604 | .maxlen = OCFS2_MAX_HB_CTL_PATH, | ||
| 605 | .mode = 0644, | ||
| 606 | .proc_handler = &proc_dostring, | ||
| 607 | .strategy = &sysctl_string, | ||
| 608 | }, | ||
| 609 | { .ctl_name = 0 } | ||
| 610 | }; | ||
| 611 | |||
| 612 | static ctl_table ocfs2_mod_table[] = { | ||
| 613 | { | ||
| 614 | .ctl_name = FS_OCFS2_NM, | ||
| 615 | .procname = "nm", | ||
| 616 | .data = NULL, | ||
| 617 | .maxlen = 0, | ||
| 618 | .mode = 0555, | ||
| 619 | .child = ocfs2_nm_table | ||
| 620 | }, | ||
| 621 | { .ctl_name = 0} | ||
| 622 | }; | ||
| 623 | |||
| 624 | static ctl_table ocfs2_kern_table[] = { | ||
| 625 | { | ||
| 626 | .ctl_name = FS_OCFS2, | ||
| 627 | .procname = "ocfs2", | ||
| 628 | .data = NULL, | ||
| 629 | .maxlen = 0, | ||
| 630 | .mode = 0555, | ||
| 631 | .child = ocfs2_mod_table | ||
| 632 | }, | ||
| 633 | { .ctl_name = 0} | ||
| 634 | }; | ||
| 635 | |||
| 636 | static ctl_table ocfs2_root_table[] = { | ||
| 637 | { | ||
| 638 | .ctl_name = CTL_FS, | ||
| 639 | .procname = "fs", | ||
| 640 | .data = NULL, | ||
| 641 | .maxlen = 0, | ||
| 642 | .mode = 0555, | ||
| 643 | .child = ocfs2_kern_table | ||
| 644 | }, | ||
| 645 | { .ctl_name = 0 } | ||
| 646 | }; | ||
| 647 | |||
| 648 | static struct ctl_table_header *ocfs2_table_header = NULL; | ||
| 649 | |||
| 650 | |||
| 651 | /* | ||
| 652 | * Initialization | ||
| 653 | */ | ||
| 654 | |||
| 551 | static int __init ocfs2_stack_glue_init(void) | 655 | static int __init ocfs2_stack_glue_init(void) |
| 552 | { | 656 | { |
| 553 | strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); | 657 | strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); |
| 554 | 658 | ||
| 659 | ocfs2_table_header = register_sysctl_table(ocfs2_root_table); | ||
| 660 | if (!ocfs2_table_header) { | ||
| 661 | printk(KERN_ERR | ||
| 662 | "ocfs2 stack glue: unable to register sysctl\n"); | ||
| 663 | return -ENOMEM; /* or something. */ | ||
| 664 | } | ||
| 665 | |||
| 555 | return ocfs2_sysfs_init(); | 666 | return ocfs2_sysfs_init(); |
| 556 | } | 667 | } |
| 557 | 668 | ||
| @@ -559,6 +670,8 @@ static void __exit ocfs2_stack_glue_exit(void) | |||
| 559 | { | 670 | { |
| 560 | lproto = NULL; | 671 | lproto = NULL; |
| 561 | ocfs2_sysfs_exit(); | 672 | ocfs2_sysfs_exit(); |
| 673 | if (ocfs2_table_header) | ||
| 674 | unregister_sysctl_table(ocfs2_table_header); | ||
| 562 | } | 675 | } |
| 563 | 676 | ||
| 564 | MODULE_AUTHOR("Oracle"); | 677 | MODULE_AUTHOR("Oracle"); |
