1 From: David Teigland <teigland@redhat.com>
2 commit dc68c7ed362a00a48290252573a8eb9f74463c3a
3 Author: David Teigland <teigland@redhat.com>
4 Date: Mon Aug 18 11:43:30 2008 -0500
5 Subject: dlm: detect available userspace daemon
7 If dlm_controld (the userspace daemon that controls the setup and
8 recovery of the dlm) fails, the kernel should shut down the lockspaces
9 in the kernel rather than leaving them running. This is detected by
10 having dlm_controld hold a misc device open while running, and if
11 the kernel detects a close while the daemon is still needed, it stops
12 the lockspaces in the kernel.
14 Knowing that the userspace daemon isn't running also allows the
15 lockspace create/remove routines to avoid waiting on the daemon
16 for join/leave operations.
18 Signed-off-by: David Teigland <teigland@redhat.com>
19 Signed-off-by: Coly Li <coly.li@suse.de>
21 diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
22 index 56eae4e..ba672fe 100644
23 --- a/fs/dlm/lockspace.c
24 +++ b/fs/dlm/lockspace.c
25 @@ -378,6 +378,11 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
26 if (!try_module_get(THIS_MODULE))
29 + if (!dlm_user_daemon_available()) {
30 + module_put(THIS_MODULE);
36 spin_lock(&lslist_lock);
37 @@ -669,7 +674,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
39 dlm_device_deregister(ls);
42 + if (force < 3 && dlm_user_daemon_available())
45 dlm_recoverd_stop(ls);
46 @@ -791,3 +796,20 @@ int dlm_release_lockspace(void *lockspace, int force)
50 +void dlm_stop_lockspaces(void)
55 + spin_lock(&lslist_lock);
56 + list_for_each_entry(ls, &lslist, ls_list) {
57 + if (!test_bit(LSFL_RUNNING, &ls->ls_flags))
59 + spin_unlock(&lslist_lock);
60 + log_error(ls, "no userland control daemon, stopping lockspace");
64 + spin_unlock(&lslist_lock);
67 diff --git a/fs/dlm/lockspace.h b/fs/dlm/lockspace.h
68 index 891eabb..f879f87 100644
69 --- a/fs/dlm/lockspace.h
70 +++ b/fs/dlm/lockspace.h
71 @@ -20,6 +20,7 @@ struct dlm_ls *dlm_find_lockspace_global(uint32_t id);
72 struct dlm_ls *dlm_find_lockspace_local(void *id);
73 struct dlm_ls *dlm_find_lockspace_device(int minor);
74 void dlm_put_lockspace(struct dlm_ls *ls);
75 +void dlm_stop_lockspaces(void);
77 #endif /* __LOCKSPACE_DOT_H__ */
79 diff --git a/fs/dlm/user.c b/fs/dlm/user.c
80 index 6542110..81627b5 100644
85 static const char name_prefix[] = "dlm";
86 static const struct file_operations device_fops;
87 +static atomic_t dlm_monitor_opened;
88 +static int dlm_monitor_unused = 1;
92 @@ -890,6 +892,26 @@ static unsigned int device_poll(struct file *file, poll_table *wait)
96 +int dlm_user_daemon_available(void)
98 + /* dlm_controld hasn't started (or, has started, but not
99 + properly populated configfs) */
101 + if (!dlm_our_nodeid())
104 + /* This is to deal with versions of dlm_controld that don't
105 + know about the monitor device. We assume that if the
106 + dlm_controld was started (above), but the monitor device
107 + was never opened, that it's an old version. dlm_controld
108 + should open the monitor device before populating configfs. */
110 + if (dlm_monitor_unused)
113 + return atomic_read(&dlm_monitor_opened) ? 1 : 0;
116 static int ctl_device_open(struct inode *inode, struct file *file)
119 @@ -902,6 +924,20 @@ static int ctl_device_close(struct inode *inode, struct file *file)
123 +static int monitor_device_open(struct inode *inode, struct file *file)
125 + atomic_inc(&dlm_monitor_opened);
126 + dlm_monitor_unused = 0;
130 +static int monitor_device_close(struct inode *inode, struct file *file)
132 + if (atomic_dec_and_test(&dlm_monitor_opened))
133 + dlm_stop_lockspaces();
137 static const struct file_operations device_fops = {
139 .release = device_close,
140 @@ -925,19 +961,42 @@ static struct miscdevice ctl_device = {
141 .minor = MISC_DYNAMIC_MINOR,
144 +static const struct file_operations monitor_device_fops = {
145 + .open = monitor_device_open,
146 + .release = monitor_device_close,
147 + .owner = THIS_MODULE,
150 +static struct miscdevice monitor_device = {
151 + .name = "dlm-monitor",
152 + .fops = &monitor_device_fops,
153 + .minor = MISC_DYNAMIC_MINOR,
156 int __init dlm_user_init(void)
160 + atomic_set(&dlm_monitor_opened, 0);
162 error = misc_register(&ctl_device);
165 log_print("misc_register failed for control device");
169 + error = misc_register(&monitor_device);
171 + log_print("misc_register failed for monitor device");
172 + misc_deregister(&ctl_device);
178 void dlm_user_exit(void)
180 misc_deregister(&ctl_device);
181 + misc_deregister(&monitor_device);
184 diff --git a/fs/dlm/user.h b/fs/dlm/user.h
185 index c528b6b..35eb6a1 100644
188 @@ -13,5 +13,6 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
189 int dlm_user_init(void);
190 void dlm_user_exit(void);
191 int dlm_device_deregister(struct dlm_ls *ls);
192 +int dlm_user_daemon_available(void);