aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2008-08-18 12:43:30 -0400
committerDavid Teigland <teigland@redhat.com>2008-08-28 12:49:43 -0400
commitdc68c7ed362a00a48290252573a8eb9f74463c3a (patch)
tree99b8b64ea08d4990373d09e01b7bac2566ad3879 /fs/dlm
parent0f8e0d9a317406612700426fad3efab0b7bbc467 (diff)
dlm: detect available userspace daemon
If dlm_controld (the userspace daemon that controls the setup and recovery of the dlm) fails, the kernel should shut down the lockspaces in the kernel rather than leaving them running. This is detected by having dlm_controld hold a misc device open while running, and if the kernel detects a close while the daemon is still needed, it stops the lockspaces in the kernel. Knowing that the userspace daemon isn't running also allows the lockspace create/remove routines to avoid waiting on the daemon for join/leave operations. Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/lockspace.c24
-rw-r--r--fs/dlm/lockspace.h1
-rw-r--r--fs/dlm/user.c61
-rw-r--r--fs/dlm/user.h1
4 files changed, 85 insertions, 2 deletions
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 56eae4e4a954..ba672fe0a601 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -378,6 +378,11 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
378 if (!try_module_get(THIS_MODULE)) 378 if (!try_module_get(THIS_MODULE))
379 return -EINVAL; 379 return -EINVAL;
380 380
381 if (!dlm_user_daemon_available()) {
382 module_put(THIS_MODULE);
383 return -EUNATCH;
384 }
385
381 error = 0; 386 error = 0;
382 387
383 spin_lock(&lslist_lock); 388 spin_lock(&lslist_lock);
@@ -669,7 +674,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
669 674
670 dlm_device_deregister(ls); 675 dlm_device_deregister(ls);
671 676
672 if (force < 3) 677 if (force < 3 && dlm_user_daemon_available())
673 do_uevent(ls, 0); 678 do_uevent(ls, 0);
674 679
675 dlm_recoverd_stop(ls); 680 dlm_recoverd_stop(ls);
@@ -791,3 +796,20 @@ int dlm_release_lockspace(void *lockspace, int force)
791 return error; 796 return error;
792} 797}
793 798
799void dlm_stop_lockspaces(void)
800{
801 struct dlm_ls *ls;
802
803 restart:
804 spin_lock(&lslist_lock);
805 list_for_each_entry(ls, &lslist, ls_list) {
806 if (!test_bit(LSFL_RUNNING, &ls->ls_flags))
807 continue;
808 spin_unlock(&lslist_lock);
809 log_error(ls, "no userland control daemon, stopping lockspace");
810 dlm_ls_stop(ls);
811 goto restart;
812 }
813 spin_unlock(&lslist_lock);
814}
815
diff --git a/fs/dlm/lockspace.h b/fs/dlm/lockspace.h
index 891eabbdd021..f879f87901f8 100644
--- a/fs/dlm/lockspace.h
+++ b/fs/dlm/lockspace.h
@@ -20,6 +20,7 @@ struct dlm_ls *dlm_find_lockspace_global(uint32_t id);
20struct dlm_ls *dlm_find_lockspace_local(void *id); 20struct dlm_ls *dlm_find_lockspace_local(void *id);
21struct dlm_ls *dlm_find_lockspace_device(int minor); 21struct dlm_ls *dlm_find_lockspace_device(int minor);
22void dlm_put_lockspace(struct dlm_ls *ls); 22void dlm_put_lockspace(struct dlm_ls *ls);
23void dlm_stop_lockspaces(void);
23 24
24#endif /* __LOCKSPACE_DOT_H__ */ 25#endif /* __LOCKSPACE_DOT_H__ */
25 26
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index 6542110c0da4..81627b502a56 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -27,6 +27,8 @@
27 27
28static const char name_prefix[] = "dlm"; 28static const char name_prefix[] = "dlm";
29static const struct file_operations device_fops; 29static const struct file_operations device_fops;
30static atomic_t dlm_monitor_opened;
31static int dlm_monitor_unused = 1;
30 32
31#ifdef CONFIG_COMPAT 33#ifdef CONFIG_COMPAT
32 34
@@ -890,6 +892,26 @@ static unsigned int device_poll(struct file *file, poll_table *wait)
890 return 0; 892 return 0;
891} 893}
892 894
895int dlm_user_daemon_available(void)
896{
897 /* dlm_controld hasn't started (or, has started, but not
898 properly populated configfs) */
899
900 if (!dlm_our_nodeid())
901 return 0;
902
903 /* This is to deal with versions of dlm_controld that don't
904 know about the monitor device. We assume that if the
905 dlm_controld was started (above), but the monitor device
906 was never opened, that it's an old version. dlm_controld
907 should open the monitor device before populating configfs. */
908
909 if (dlm_monitor_unused)
910 return 1;
911
912 return atomic_read(&dlm_monitor_opened) ? 1 : 0;
913}
914
893static int ctl_device_open(struct inode *inode, struct file *file) 915static int ctl_device_open(struct inode *inode, struct file *file)
894{ 916{
895 cycle_kernel_lock(); 917 cycle_kernel_lock();
@@ -902,6 +924,20 @@ static int ctl_device_close(struct inode *inode, struct file *file)
902 return 0; 924 return 0;
903} 925}
904 926
927static int monitor_device_open(struct inode *inode, struct file *file)
928{
929 atomic_inc(&dlm_monitor_opened);
930 dlm_monitor_unused = 0;
931 return 0;
932}
933
934static int monitor_device_close(struct inode *inode, struct file *file)
935{
936 if (atomic_dec_and_test(&dlm_monitor_opened))
937 dlm_stop_lockspaces();
938 return 0;
939}
940
905static const struct file_operations device_fops = { 941static const struct file_operations device_fops = {
906 .open = device_open, 942 .open = device_open,
907 .release = device_close, 943 .release = device_close,
@@ -925,19 +961,42 @@ static struct miscdevice ctl_device = {
925 .minor = MISC_DYNAMIC_MINOR, 961 .minor = MISC_DYNAMIC_MINOR,
926}; 962};
927 963
964static const struct file_operations monitor_device_fops = {
965 .open = monitor_device_open,
966 .release = monitor_device_close,
967 .owner = THIS_MODULE,
968};
969
970static struct miscdevice monitor_device = {
971 .name = "dlm-monitor",
972 .fops = &monitor_device_fops,
973 .minor = MISC_DYNAMIC_MINOR,
974};
975
928int __init dlm_user_init(void) 976int __init dlm_user_init(void)
929{ 977{
930 int error; 978 int error;
931 979
980 atomic_set(&dlm_monitor_opened, 0);
981
932 error = misc_register(&ctl_device); 982 error = misc_register(&ctl_device);
933 if (error) 983 if (error) {
934 log_print("misc_register failed for control device"); 984 log_print("misc_register failed for control device");
985 goto out;
986 }
935 987
988 error = misc_register(&monitor_device);
989 if (error) {
990 log_print("misc_register failed for monitor device");
991 misc_deregister(&ctl_device);
992 }
993 out:
936 return error; 994 return error;
937} 995}
938 996
939void dlm_user_exit(void) 997void dlm_user_exit(void)
940{ 998{
941 misc_deregister(&ctl_device); 999 misc_deregister(&ctl_device);
1000 misc_deregister(&monitor_device);
942} 1001}
943 1002
diff --git a/fs/dlm/user.h b/fs/dlm/user.h
index c528b6b2991b..35eb6a13d616 100644
--- a/fs/dlm/user.h
+++ b/fs/dlm/user.h
@@ -13,5 +13,6 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
13int dlm_user_init(void); 13int dlm_user_init(void);
14void dlm_user_exit(void); 14void dlm_user_exit(void);
15int dlm_device_deregister(struct dlm_ls *ls); 15int dlm_device_deregister(struct dlm_ls *ls);
16int dlm_user_daemon_available(void);
16 17
17#endif 18#endif