]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
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 | |
6 | ||
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. | |
13 | ||
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. | |
17 | ||
18 | Signed-off-by: David Teigland <teigland@redhat.com> | |
19 | Signed-off-by: Coly Li <coly.li@suse.de> | |
20 | ||
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)) | |
27 | return -EINVAL; | |
28 | ||
29 | + if (!dlm_user_daemon_available()) { | |
30 | + module_put(THIS_MODULE); | |
31 | + return -EUNATCH; | |
32 | + } | |
33 | + | |
34 | error = 0; | |
35 | ||
36 | spin_lock(&lslist_lock); | |
37 | @@ -669,7 +674,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |
38 | ||
39 | dlm_device_deregister(ls); | |
40 | ||
41 | - if (force < 3) | |
42 | + if (force < 3 && dlm_user_daemon_available()) | |
43 | do_uevent(ls, 0); | |
44 | ||
45 | dlm_recoverd_stop(ls); | |
46 | @@ -791,3 +796,20 @@ int dlm_release_lockspace(void *lockspace, int force) | |
47 | return error; | |
48 | } | |
49 | ||
50 | +void dlm_stop_lockspaces(void) | |
51 | +{ | |
52 | + struct dlm_ls *ls; | |
53 | + | |
54 | + restart: | |
55 | + spin_lock(&lslist_lock); | |
56 | + list_for_each_entry(ls, &lslist, ls_list) { | |
57 | + if (!test_bit(LSFL_RUNNING, &ls->ls_flags)) | |
58 | + continue; | |
59 | + spin_unlock(&lslist_lock); | |
60 | + log_error(ls, "no userland control daemon, stopping lockspace"); | |
61 | + dlm_ls_stop(ls); | |
62 | + goto restart; | |
63 | + } | |
64 | + spin_unlock(&lslist_lock); | |
65 | +} | |
66 | + | |
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); | |
76 | ||
77 | #endif /* __LOCKSPACE_DOT_H__ */ | |
78 | ||
79 | diff --git a/fs/dlm/user.c b/fs/dlm/user.c | |
80 | index 6542110..81627b5 100644 | |
81 | --- a/fs/dlm/user.c | |
82 | +++ b/fs/dlm/user.c | |
83 | @@ -27,6 +27,8 @@ | |
84 | ||
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; | |
89 | ||
90 | #ifdef CONFIG_COMPAT | |
91 | ||
92 | @@ -890,6 +892,26 @@ static unsigned int device_poll(struct file *file, poll_table *wait) | |
93 | return 0; | |
94 | } | |
95 | ||
96 | +int dlm_user_daemon_available(void) | |
97 | +{ | |
98 | + /* dlm_controld hasn't started (or, has started, but not | |
99 | + properly populated configfs) */ | |
100 | + | |
101 | + if (!dlm_our_nodeid()) | |
102 | + return 0; | |
103 | + | |
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. */ | |
109 | + | |
110 | + if (dlm_monitor_unused) | |
111 | + return 1; | |
112 | + | |
113 | + return atomic_read(&dlm_monitor_opened) ? 1 : 0; | |
114 | +} | |
115 | + | |
116 | static int ctl_device_open(struct inode *inode, struct file *file) | |
117 | { | |
118 | cycle_kernel_lock(); | |
119 | @@ -902,6 +924,20 @@ static int ctl_device_close(struct inode *inode, struct file *file) | |
120 | return 0; | |
121 | } | |
122 | ||
123 | +static int monitor_device_open(struct inode *inode, struct file *file) | |
124 | +{ | |
125 | + atomic_inc(&dlm_monitor_opened); | |
126 | + dlm_monitor_unused = 0; | |
127 | + return 0; | |
128 | +} | |
129 | + | |
130 | +static int monitor_device_close(struct inode *inode, struct file *file) | |
131 | +{ | |
132 | + if (atomic_dec_and_test(&dlm_monitor_opened)) | |
133 | + dlm_stop_lockspaces(); | |
134 | + return 0; | |
135 | +} | |
136 | + | |
137 | static const struct file_operations device_fops = { | |
138 | .open = device_open, | |
139 | .release = device_close, | |
140 | @@ -925,19 +961,42 @@ static struct miscdevice ctl_device = { | |
141 | .minor = MISC_DYNAMIC_MINOR, | |
142 | }; | |
143 | ||
144 | +static const struct file_operations monitor_device_fops = { | |
145 | + .open = monitor_device_open, | |
146 | + .release = monitor_device_close, | |
147 | + .owner = THIS_MODULE, | |
148 | +}; | |
149 | + | |
150 | +static struct miscdevice monitor_device = { | |
151 | + .name = "dlm-monitor", | |
152 | + .fops = &monitor_device_fops, | |
153 | + .minor = MISC_DYNAMIC_MINOR, | |
154 | +}; | |
155 | + | |
156 | int __init dlm_user_init(void) | |
157 | { | |
158 | int error; | |
159 | ||
160 | + atomic_set(&dlm_monitor_opened, 0); | |
161 | + | |
162 | error = misc_register(&ctl_device); | |
163 | - if (error) | |
164 | + if (error) { | |
165 | log_print("misc_register failed for control device"); | |
166 | + goto out; | |
167 | + } | |
168 | ||
169 | + error = misc_register(&monitor_device); | |
170 | + if (error) { | |
171 | + log_print("misc_register failed for monitor device"); | |
172 | + misc_deregister(&ctl_device); | |
173 | + } | |
174 | + out: | |
175 | return error; | |
176 | } | |
177 | ||
178 | void dlm_user_exit(void) | |
179 | { | |
180 | misc_deregister(&ctl_device); | |
181 | + misc_deregister(&monitor_device); | |
182 | } | |
183 | ||
184 | diff --git a/fs/dlm/user.h b/fs/dlm/user.h | |
185 | index c528b6b..35eb6a1 100644 | |
186 | --- a/fs/dlm/user.h | |
187 | +++ b/fs/dlm/user.h | |
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); | |
193 | ||
194 | #endif |