blob: b14bb2c4604263e0d9be31bc1ad14545959a15b7 [file] [log] [blame]
David Teiglande7fd4172006-01-18 09:30:29 +00001/******************************************************************************
2*******************************************************************************
3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
David Teigland60f98d12011-11-02 14:30:58 -05005** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
David Teiglande7fd4172006-01-18 09:30:29 +00006**
7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions
9** of the GNU General Public License v.2.
10**
11*******************************************************************************
12******************************************************************************/
13
14#include "dlm_internal.h"
15#include "lockspace.h"
16#include "member.h"
17#include "recoverd.h"
David Teiglande7fd4172006-01-18 09:30:29 +000018#include "dir.h"
19#include "lowcomms.h"
20#include "config.h"
21#include "memory.h"
22#include "lock.h"
David Teiglandc56b39c2006-04-28 10:51:53 -040023#include "recover.h"
David Teigland2896ee32006-11-27 11:31:22 -060024#include "requestqueue.h"
David Teigland0f8e0d92008-08-06 13:30:24 -050025#include "user.h"
David Teigland23e8e1a2011-04-05 13:16:24 -050026#include "ast.h"
David Teiglande7fd4172006-01-18 09:30:29 +000027
David Teiglande7fd4172006-01-18 09:30:29 +000028static int ls_count;
David Teigland90135922006-01-20 08:47:07 +000029static struct mutex ls_lock;
David Teiglande7fd4172006-01-18 09:30:29 +000030static struct list_head lslist;
31static spinlock_t lslist_lock;
32static struct task_struct * scand_task;
33
34
35static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
36{
37 ssize_t ret = len;
Fabian Frederick6edb5682014-06-06 14:38:25 -070038 int n;
39 int rc = kstrtoint(buf, 0, &n);
David Teiglande7fd4172006-01-18 09:30:29 +000040
Fabian Frederick6edb5682014-06-06 14:38:25 -070041 if (rc)
42 return rc;
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000043 ls = dlm_find_lockspace_local(ls->ls_local_handle);
44 if (!ls)
45 return -EINVAL;
46
David Teiglande7fd4172006-01-18 09:30:29 +000047 switch (n) {
48 case 0:
49 dlm_ls_stop(ls);
50 break;
51 case 1:
52 dlm_ls_start(ls);
53 break;
54 default:
55 ret = -EINVAL;
56 }
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000057 dlm_put_lockspace(ls);
David Teiglande7fd4172006-01-18 09:30:29 +000058 return ret;
59}
60
61static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
62{
Fabian Frederick6edb5682014-06-06 14:38:25 -070063 int rc = kstrtoint(buf, 0, &ls->ls_uevent_result);
64
65 if (rc)
66 return rc;
David Teiglande7fd4172006-01-18 09:30:29 +000067 set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
68 wake_up(&ls->ls_uevent_wait);
69 return len;
70}
71
72static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
73{
David Teiglanda1d144c2006-09-06 17:01:40 -050074 return snprintf(buf, PAGE_SIZE, "%u\n", ls->ls_global_id);
David Teiglande7fd4172006-01-18 09:30:29 +000075}
76
77static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
78{
Fabian Frederick6edb5682014-06-06 14:38:25 -070079 int rc = kstrtouint(buf, 0, &ls->ls_global_id);
80
81 if (rc)
82 return rc;
David Teiglande7fd4172006-01-18 09:30:29 +000083 return len;
84}
85
David Teigland48756472012-04-26 15:54:29 -050086static ssize_t dlm_nodir_show(struct dlm_ls *ls, char *buf)
87{
88 return snprintf(buf, PAGE_SIZE, "%u\n", dlm_no_directory(ls));
89}
90
91static ssize_t dlm_nodir_store(struct dlm_ls *ls, const char *buf, size_t len)
92{
Fabian Frederick6edb5682014-06-06 14:38:25 -070093 int val;
94 int rc = kstrtoint(buf, 0, &val);
95
96 if (rc)
97 return rc;
David Teigland48756472012-04-26 15:54:29 -050098 if (val == 1)
99 set_bit(LSFL_NODIR, &ls->ls_flags);
100 return len;
101}
102
David Teiglandc56b39c2006-04-28 10:51:53 -0400103static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
104{
105 uint32_t status = dlm_recover_status(ls);
David Teiglanda1d144c2006-09-06 17:01:40 -0500106 return snprintf(buf, PAGE_SIZE, "%x\n", status);
David Teiglandc56b39c2006-04-28 10:51:53 -0400107}
108
David Teiglandfaa0f262006-08-08 17:08:42 -0500109static ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf)
110{
David Teiglanda1d144c2006-09-06 17:01:40 -0500111 return snprintf(buf, PAGE_SIZE, "%d\n", ls->ls_recover_nodeid);
David Teiglandfaa0f262006-08-08 17:08:42 -0500112}
113
David Teiglande7fd4172006-01-18 09:30:29 +0000114struct dlm_attr {
115 struct attribute attr;
116 ssize_t (*show)(struct dlm_ls *, char *);
117 ssize_t (*store)(struct dlm_ls *, const char *, size_t);
118};
119
120static struct dlm_attr dlm_attr_control = {
121 .attr = {.name = "control", .mode = S_IWUSR},
122 .store = dlm_control_store
123};
124
125static struct dlm_attr dlm_attr_event = {
126 .attr = {.name = "event_done", .mode = S_IWUSR},
127 .store = dlm_event_store
128};
129
130static struct dlm_attr dlm_attr_id = {
131 .attr = {.name = "id", .mode = S_IRUGO | S_IWUSR},
132 .show = dlm_id_show,
133 .store = dlm_id_store
134};
135
David Teigland48756472012-04-26 15:54:29 -0500136static struct dlm_attr dlm_attr_nodir = {
137 .attr = {.name = "nodir", .mode = S_IRUGO | S_IWUSR},
138 .show = dlm_nodir_show,
139 .store = dlm_nodir_store
140};
141
David Teiglandc56b39c2006-04-28 10:51:53 -0400142static struct dlm_attr dlm_attr_recover_status = {
143 .attr = {.name = "recover_status", .mode = S_IRUGO},
144 .show = dlm_recover_status_show
145};
146
David Teiglandfaa0f262006-08-08 17:08:42 -0500147static struct dlm_attr dlm_attr_recover_nodeid = {
148 .attr = {.name = "recover_nodeid", .mode = S_IRUGO},
149 .show = dlm_recover_nodeid_show
150};
151
David Teiglande7fd4172006-01-18 09:30:29 +0000152static struct attribute *dlm_attrs[] = {
153 &dlm_attr_control.attr,
154 &dlm_attr_event.attr,
155 &dlm_attr_id.attr,
David Teigland48756472012-04-26 15:54:29 -0500156 &dlm_attr_nodir.attr,
David Teiglandc56b39c2006-04-28 10:51:53 -0400157 &dlm_attr_recover_status.attr,
David Teiglandfaa0f262006-08-08 17:08:42 -0500158 &dlm_attr_recover_nodeid.attr,
David Teiglande7fd4172006-01-18 09:30:29 +0000159 NULL,
160};
161
162static ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr,
163 char *buf)
164{
165 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
166 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
167 return a->show ? a->show(ls, buf) : 0;
168}
169
170static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
171 const char *buf, size_t len)
172{
173 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
174 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
175 return a->store ? a->store(ls, buf, len) : len;
176}
177
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000178static void lockspace_kobj_release(struct kobject *k)
179{
180 struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj);
181 kfree(ls);
182}
183
Emese Revfy52cf25d2010-01-19 02:58:23 +0100184static const struct sysfs_ops dlm_attr_ops = {
David Teiglande7fd4172006-01-18 09:30:29 +0000185 .show = dlm_attr_show,
186 .store = dlm_attr_store,
187};
188
189static struct kobj_type dlm_ktype = {
190 .default_attrs = dlm_attrs,
191 .sysfs_ops = &dlm_attr_ops,
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000192 .release = lockspace_kobj_release,
David Teiglande7fd4172006-01-18 09:30:29 +0000193};
194
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100195static struct kset *dlm_kset;
David Teiglande7fd4172006-01-18 09:30:29 +0000196
David Teiglande7fd4172006-01-18 09:30:29 +0000197static int do_uevent(struct dlm_ls *ls, int in)
198{
199 int error;
200
201 if (in)
202 kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
203 else
204 kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
205
David Teigland075f0172014-02-14 11:54:44 -0600206 log_rinfo(ls, "%s the lockspace group...", in ? "joining" : "leaving");
David Teigland8b0e7b22007-05-18 09:03:35 -0500207
208 /* dlm_controld will see the uevent, do the necessary group management
209 and then write to sysfs to wake us */
210
David Teiglande7fd4172006-01-18 09:30:29 +0000211 error = wait_event_interruptible(ls->ls_uevent_wait,
212 test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
David Teigland8b0e7b22007-05-18 09:03:35 -0500213
David Teigland075f0172014-02-14 11:54:44 -0600214 log_rinfo(ls, "group event done %d %d", error, ls->ls_uevent_result);
David Teigland8b0e7b22007-05-18 09:03:35 -0500215
David Teiglande7fd4172006-01-18 09:30:29 +0000216 if (error)
217 goto out;
218
219 error = ls->ls_uevent_result;
220 out:
David Teigland8b0e7b22007-05-18 09:03:35 -0500221 if (error)
222 log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
223 error, ls->ls_uevent_result);
David Teiglande7fd4172006-01-18 09:30:29 +0000224 return error;
225}
226
Steven Whitehouseb4a5d4b2010-02-17 09:41:34 +0000227static int dlm_uevent(struct kset *kset, struct kobject *kobj,
228 struct kobj_uevent_env *env)
229{
230 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
231
232 add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
233 return 0;
234}
235
236static struct kset_uevent_ops dlm_uevent_ops = {
237 .uevent = dlm_uevent,
238};
David Teiglande7fd4172006-01-18 09:30:29 +0000239
Denis Cheng30727172008-02-02 01:53:46 +0800240int __init dlm_lockspace_init(void)
David Teiglande7fd4172006-01-18 09:30:29 +0000241{
David Teiglande7fd4172006-01-18 09:30:29 +0000242 ls_count = 0;
David Teigland90135922006-01-20 08:47:07 +0000243 mutex_init(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000244 INIT_LIST_HEAD(&lslist);
245 spin_lock_init(&lslist_lock);
246
Steven Whitehouseb4a5d4b2010-02-17 09:41:34 +0000247 dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100248 if (!dlm_kset) {
Harvey Harrison8e24eea2008-04-30 00:55:09 -0700249 printk(KERN_WARNING "%s: can not create kset\n", __func__);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100250 return -ENOMEM;
251 }
252 return 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000253}
254
255void dlm_lockspace_exit(void)
256{
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100257 kset_unregister(dlm_kset);
David Teiglande7fd4172006-01-18 09:30:29 +0000258}
259
David Teiglandc1dcf652008-08-18 14:03:25 -0500260static struct dlm_ls *find_ls_to_scan(void)
David Teiglande7fd4172006-01-18 09:30:29 +0000261{
262 struct dlm_ls *ls;
263
David Teiglandc1dcf652008-08-18 14:03:25 -0500264 spin_lock(&lslist_lock);
265 list_for_each_entry(ls, &lslist, ls_list) {
266 if (time_after_eq(jiffies, ls->ls_scan_time +
267 dlm_config.ci_scan_secs * HZ)) {
268 spin_unlock(&lslist_lock);
269 return ls;
270 }
271 }
272 spin_unlock(&lslist_lock);
273 return NULL;
274}
275
276static int dlm_scand(void *data)
277{
278 struct dlm_ls *ls;
David Teiglandc1dcf652008-08-18 14:03:25 -0500279
David Teiglande7fd4172006-01-18 09:30:29 +0000280 while (!kthread_should_stop()) {
David Teiglandc1dcf652008-08-18 14:03:25 -0500281 ls = find_ls_to_scan();
282 if (ls) {
David Teigland85e86ed2007-05-18 08:58:15 -0500283 if (dlm_lock_recovery_try(ls)) {
David Teiglandc1dcf652008-08-18 14:03:25 -0500284 ls->ls_scan_time = jiffies;
David Teigland85e86ed2007-05-18 08:58:15 -0500285 dlm_scan_rsbs(ls);
David Teigland3ae1acf2007-05-18 08:59:31 -0500286 dlm_scan_timeout(ls);
David Teiglandc6ff6692011-03-28 14:17:26 -0500287 dlm_scan_waiters(ls);
David Teigland85e86ed2007-05-18 08:58:15 -0500288 dlm_unlock_recovery(ls);
David Teiglandc1dcf652008-08-18 14:03:25 -0500289 } else {
290 ls->ls_scan_time += HZ;
David Teigland85e86ed2007-05-18 08:58:15 -0500291 }
David Teiglandc6ff6692011-03-28 14:17:26 -0500292 continue;
David Teigland85e86ed2007-05-18 08:58:15 -0500293 }
David Teiglandc6ff6692011-03-28 14:17:26 -0500294 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
David Teiglande7fd4172006-01-18 09:30:29 +0000295 }
296 return 0;
297}
298
299static int dlm_scand_start(void)
300{
301 struct task_struct *p;
302 int error = 0;
303
304 p = kthread_run(dlm_scand, NULL, "dlm_scand");
305 if (IS_ERR(p))
306 error = PTR_ERR(p);
307 else
308 scand_task = p;
309 return error;
310}
311
312static void dlm_scand_stop(void)
313{
314 kthread_stop(scand_task);
315}
316
David Teiglande7fd4172006-01-18 09:30:29 +0000317struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
318{
319 struct dlm_ls *ls;
320
321 spin_lock(&lslist_lock);
322
323 list_for_each_entry(ls, &lslist, ls_list) {
324 if (ls->ls_global_id == id) {
325 ls->ls_count++;
326 goto out;
327 }
328 }
329 ls = NULL;
330 out:
331 spin_unlock(&lslist_lock);
332 return ls;
333}
334
David Teigland597d0ca2006-07-12 16:44:04 -0500335struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000336{
David Teigland597d0ca2006-07-12 16:44:04 -0500337 struct dlm_ls *ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000338
339 spin_lock(&lslist_lock);
David Teigland597d0ca2006-07-12 16:44:04 -0500340 list_for_each_entry(ls, &lslist, ls_list) {
341 if (ls->ls_local_handle == lockspace) {
342 ls->ls_count++;
343 goto out;
344 }
345 }
346 ls = NULL;
347 out:
348 spin_unlock(&lslist_lock);
349 return ls;
350}
351
352struct dlm_ls *dlm_find_lockspace_device(int minor)
353{
354 struct dlm_ls *ls;
355
356 spin_lock(&lslist_lock);
357 list_for_each_entry(ls, &lslist, ls_list) {
358 if (ls->ls_device.minor == minor) {
359 ls->ls_count++;
360 goto out;
361 }
362 }
363 ls = NULL;
364 out:
David Teiglande7fd4172006-01-18 09:30:29 +0000365 spin_unlock(&lslist_lock);
366 return ls;
367}
368
369void dlm_put_lockspace(struct dlm_ls *ls)
370{
371 spin_lock(&lslist_lock);
372 ls->ls_count--;
373 spin_unlock(&lslist_lock);
374}
375
376static void remove_lockspace(struct dlm_ls *ls)
377{
378 for (;;) {
379 spin_lock(&lslist_lock);
380 if (ls->ls_count == 0) {
David Teigland0f8e0d92008-08-06 13:30:24 -0500381 WARN_ON(ls->ls_create_count != 0);
David Teiglande7fd4172006-01-18 09:30:29 +0000382 list_del(&ls->ls_list);
383 spin_unlock(&lslist_lock);
384 return;
385 }
386 spin_unlock(&lslist_lock);
387 ssleep(1);
388 }
389}
390
391static int threads_start(void)
392{
393 int error;
394
David Teiglande7fd4172006-01-18 09:30:29 +0000395 error = dlm_scand_start();
396 if (error) {
397 log_print("cannot start dlm_scand thread %d", error);
David Teigland23e8e1a2011-04-05 13:16:24 -0500398 goto fail;
David Teiglande7fd4172006-01-18 09:30:29 +0000399 }
400
401 /* Thread for sending/receiving messages for all lockspace's */
402 error = dlm_lowcomms_start();
403 if (error) {
404 log_print("cannot start dlm lowcomms %d", error);
405 goto scand_fail;
406 }
407
408 return 0;
409
410 scand_fail:
411 dlm_scand_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000412 fail:
413 return error;
414}
415
416static void threads_stop(void)
417{
418 dlm_scand_stop();
419 dlm_lowcomms_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000420}
421
David Teigland60f98d12011-11-02 14:30:58 -0500422static int new_lockspace(const char *name, const char *cluster,
423 uint32_t flags, int lvblen,
424 const struct dlm_lockspace_ops *ops, void *ops_arg,
425 int *ops_result, dlm_lockspace_t **lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000426{
427 struct dlm_ls *ls;
David Teigland0f8e0d92008-08-06 13:30:24 -0500428 int i, size, error;
David Teigland79d72b52007-05-18 09:02:20 -0500429 int do_unreg = 0;
David Teigland60f98d12011-11-02 14:30:58 -0500430 int namelen = strlen(name);
David Teiglande7fd4172006-01-18 09:30:29 +0000431
432 if (namelen > DLM_LOCKSPACE_LEN)
433 return -EINVAL;
434
435 if (!lvblen || (lvblen % 8))
436 return -EINVAL;
437
438 if (!try_module_get(THIS_MODULE))
439 return -EINVAL;
440
David Teiglanddc68c7e2008-08-18 11:43:30 -0500441 if (!dlm_user_daemon_available()) {
David Teigland60f98d12011-11-02 14:30:58 -0500442 log_print("dlm user daemon not available");
443 error = -EUNATCH;
444 goto out;
445 }
446
447 if (ops && ops_result) {
448 if (!dlm_config.ci_recover_callbacks)
449 *ops_result = -EOPNOTSUPP;
450 else
451 *ops_result = 0;
452 }
453
454 if (dlm_config.ci_recover_callbacks && cluster &&
455 strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) {
456 log_print("dlm cluster name %s mismatch %s",
457 dlm_config.ci_cluster_name, cluster);
458 error = -EBADR;
459 goto out;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500460 }
461
David Teigland0f8e0d92008-08-06 13:30:24 -0500462 error = 0;
463
464 spin_lock(&lslist_lock);
465 list_for_each_entry(ls, &lslist, ls_list) {
466 WARN_ON(ls->ls_create_count <= 0);
467 if (ls->ls_namelen != namelen)
468 continue;
469 if (memcmp(ls->ls_name, name, namelen))
470 continue;
471 if (flags & DLM_LSFL_NEWEXCL) {
472 error = -EEXIST;
473 break;
474 }
475 ls->ls_create_count++;
David Teigland8511a272009-04-08 15:38:43 -0500476 *lockspace = ls;
477 error = 1;
David Teigland0f8e0d92008-08-06 13:30:24 -0500478 break;
David Teiglande7fd4172006-01-18 09:30:29 +0000479 }
David Teigland0f8e0d92008-08-06 13:30:24 -0500480 spin_unlock(&lslist_lock);
481
David Teigland0f8e0d92008-08-06 13:30:24 -0500482 if (error)
David Teigland8511a272009-04-08 15:38:43 -0500483 goto out;
David Teigland0f8e0d92008-08-06 13:30:24 -0500484
485 error = -ENOMEM;
David Teiglande7fd4172006-01-18 09:30:29 +0000486
David Teigland573c24c2009-11-30 16:34:43 -0600487 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_NOFS);
David Teiglande7fd4172006-01-18 09:30:29 +0000488 if (!ls)
489 goto out;
David Teiglande7fd4172006-01-18 09:30:29 +0000490 memcpy(ls->ls_name, name, namelen);
491 ls->ls_namelen = namelen;
David Teiglande7fd4172006-01-18 09:30:29 +0000492 ls->ls_lvblen = lvblen;
493 ls->ls_count = 0;
494 ls->ls_flags = 0;
David Teiglandc1dcf652008-08-18 14:03:25 -0500495 ls->ls_scan_time = jiffies;
David Teiglande7fd4172006-01-18 09:30:29 +0000496
David Teigland60f98d12011-11-02 14:30:58 -0500497 if (ops && dlm_config.ci_recover_callbacks) {
498 ls->ls_ops = ops;
499 ls->ls_ops_arg = ops_arg;
500 }
501
David Teigland3ae1acf2007-05-18 08:59:31 -0500502 if (flags & DLM_LSFL_TIMEWARN)
503 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
David Teigland3ae1acf2007-05-18 08:59:31 -0500504
David Teiglandfad59c12007-06-11 10:47:18 -0500505 /* ls_exflags are forced to match among nodes, and we don't
David Teigland0f8e0d92008-08-06 13:30:24 -0500506 need to require all nodes to have some flags set */
507 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
508 DLM_LSFL_NEWEXCL));
David Teiglandfad59c12007-06-11 10:47:18 -0500509
David Teigland68c817a2007-01-09 09:41:48 -0600510 size = dlm_config.ci_rsbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000511 ls->ls_rsbtbl_size = size;
512
Bryn M. Reevesc282af42011-07-01 15:49:23 -0500513 ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
David Teiglande7fd4172006-01-18 09:30:29 +0000514 if (!ls->ls_rsbtbl)
515 goto out_lsfree;
516 for (i = 0; i < size; i++) {
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500517 ls->ls_rsbtbl[i].keep.rb_node = NULL;
518 ls->ls_rsbtbl[i].toss.rb_node = NULL;
David Teiglandc7be7612009-01-07 16:50:41 -0600519 spin_lock_init(&ls->ls_rsbtbl[i].lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000520 }
521
David Teigland05c32f42012-06-14 12:17:32 -0500522 spin_lock_init(&ls->ls_remove_spin);
523
524 for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
525 ls->ls_remove_names[i] = kzalloc(DLM_RESNAME_MAXLEN+1,
526 GFP_KERNEL);
527 if (!ls->ls_remove_names[i])
528 goto out_rsbtbl;
529 }
530
David Teigland3d6aa672011-07-06 17:00:54 -0500531 idr_init(&ls->ls_lkbidr);
532 spin_lock_init(&ls->ls_lkbidr_spin);
David Teiglande7fd4172006-01-18 09:30:29 +0000533
David Teiglande7fd4172006-01-18 09:30:29 +0000534 INIT_LIST_HEAD(&ls->ls_waiters);
David Teigland90135922006-01-20 08:47:07 +0000535 mutex_init(&ls->ls_waiters_mutex);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500536 INIT_LIST_HEAD(&ls->ls_orphans);
537 mutex_init(&ls->ls_orphans_mutex);
David Teigland3ae1acf2007-05-18 08:59:31 -0500538 INIT_LIST_HEAD(&ls->ls_timeout);
539 mutex_init(&ls->ls_timeout_mutex);
David Teiglande7fd4172006-01-18 09:30:29 +0000540
David Teigland3881ac02011-07-07 14:05:03 -0500541 INIT_LIST_HEAD(&ls->ls_new_rsb);
542 spin_lock_init(&ls->ls_new_rsb_spin);
543
David Teiglande7fd4172006-01-18 09:30:29 +0000544 INIT_LIST_HEAD(&ls->ls_nodes);
545 INIT_LIST_HEAD(&ls->ls_nodes_gone);
546 ls->ls_num_nodes = 0;
547 ls->ls_low_nodeid = 0;
548 ls->ls_total_weight = 0;
549 ls->ls_node_array = NULL;
550
551 memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
552 ls->ls_stub_rsb.res_ls = ls;
553
David Teigland5de63192006-07-25 13:44:31 -0500554 ls->ls_debug_rsb_dentry = NULL;
555 ls->ls_debug_waiters_dentry = NULL;
David Teiglande7fd4172006-01-18 09:30:29 +0000556
557 init_waitqueue_head(&ls->ls_uevent_wait);
558 ls->ls_uevent_result = 0;
David Teigland8b0e7b22007-05-18 09:03:35 -0500559 init_completion(&ls->ls_members_done);
560 ls->ls_members_result = -1;
David Teiglande7fd4172006-01-18 09:30:29 +0000561
David Teigland23e8e1a2011-04-05 13:16:24 -0500562 mutex_init(&ls->ls_cb_mutex);
563 INIT_LIST_HEAD(&ls->ls_cb_delay);
564
David Teiglande7fd4172006-01-18 09:30:29 +0000565 ls->ls_recoverd_task = NULL;
David Teigland90135922006-01-20 08:47:07 +0000566 mutex_init(&ls->ls_recoverd_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000567 spin_lock_init(&ls->ls_recover_lock);
David Teigland98f176f2006-11-27 13:19:28 -0600568 spin_lock_init(&ls->ls_rcom_spin);
569 get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
David Teiglande7fd4172006-01-18 09:30:29 +0000570 ls->ls_recover_status = 0;
571 ls->ls_recover_seq = 0;
572 ls->ls_recover_args = NULL;
573 init_rwsem(&ls->ls_in_recovery);
David Teiglandc36258b2007-09-27 15:53:38 -0500574 init_rwsem(&ls->ls_recv_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000575 INIT_LIST_HEAD(&ls->ls_requestqueue);
David Teigland90135922006-01-20 08:47:07 +0000576 mutex_init(&ls->ls_requestqueue_mutex);
David Teigland597d0ca2006-07-12 16:44:04 -0500577 mutex_init(&ls->ls_clear_proc_locks);
David Teiglande7fd4172006-01-18 09:30:29 +0000578
David Teigland573c24c2009-11-30 16:34:43 -0600579 ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
David Teiglande7fd4172006-01-18 09:30:29 +0000580 if (!ls->ls_recover_buf)
David Teigland05c32f42012-06-14 12:17:32 -0500581 goto out_lkbidr;
David Teiglande7fd4172006-01-18 09:30:29 +0000582
David Teigland757a4272011-10-20 13:26:28 -0500583 ls->ls_slot = 0;
584 ls->ls_num_slots = 0;
585 ls->ls_slots_size = 0;
586 ls->ls_slots = NULL;
587
David Teiglande7fd4172006-01-18 09:30:29 +0000588 INIT_LIST_HEAD(&ls->ls_recover_list);
589 spin_lock_init(&ls->ls_recover_list_lock);
David Teigland1d7c4842012-05-15 16:07:49 -0500590 idr_init(&ls->ls_recover_idr);
591 spin_lock_init(&ls->ls_recover_idr_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000592 ls->ls_recover_list_count = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500593 ls->ls_local_handle = ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000594 init_waitqueue_head(&ls->ls_wait_general);
595 INIT_LIST_HEAD(&ls->ls_root_list);
596 init_rwsem(&ls->ls_root_sem);
597
David Teigland5f88f1e2006-08-24 14:47:20 -0500598 spin_lock(&lslist_lock);
David Teigland0f8e0d92008-08-06 13:30:24 -0500599 ls->ls_create_count = 1;
David Teigland5f88f1e2006-08-24 14:47:20 -0500600 list_add(&ls->ls_list, &lslist);
601 spin_unlock(&lslist_lock);
602
David Teigland23e8e1a2011-04-05 13:16:24 -0500603 if (flags & DLM_LSFL_FS) {
604 error = dlm_callback_start(ls);
605 if (error) {
606 log_error(ls, "can't start dlm_callback %d", error);
607 goto out_delist;
608 }
609 }
610
David Teigland475f2302012-08-02 11:08:21 -0500611 init_waitqueue_head(&ls->ls_recover_lock_wait);
612
613 /*
614 * Once started, dlm_recoverd first looks for ls in lslist, then
615 * initializes ls_in_recovery as locked in "down" mode. We need
616 * to wait for the wakeup from dlm_recoverd because in_recovery
617 * has to start out in down mode.
618 */
619
David Teiglande7fd4172006-01-18 09:30:29 +0000620 error = dlm_recoverd_start(ls);
621 if (error) {
622 log_error(ls, "can't start dlm_recoverd %d", error);
David Teigland23e8e1a2011-04-05 13:16:24 -0500623 goto out_callback;
David Teiglande7fd4172006-01-18 09:30:29 +0000624 }
625
David Teigland475f2302012-08-02 11:08:21 -0500626 wait_event(ls->ls_recover_lock_wait,
627 test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
628
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400629 ls->ls_kobj.kset = dlm_kset;
630 error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
631 "%s", ls->ls_name);
David Teiglande7fd4172006-01-18 09:30:29 +0000632 if (error)
David Teigland23e8e1a2011-04-05 13:16:24 -0500633 goto out_recoverd;
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400634 kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
David Teigland79d72b52007-05-18 09:02:20 -0500635
636 /* let kobject handle freeing of ls if there's an error */
637 do_unreg = 1;
David Teiglande7fd4172006-01-18 09:30:29 +0000638
David Teigland8b0e7b22007-05-18 09:03:35 -0500639 /* This uevent triggers dlm_controld in userspace to add us to the
640 group of nodes that are members of this lockspace (managed by the
641 cluster infrastructure.) Once it's done that, it tells us who the
642 current lockspace members are (via configfs) and then tells the
643 lockspace to start running (via sysfs) in dlm_ls_start(). */
644
David Teiglande7fd4172006-01-18 09:30:29 +0000645 error = do_uevent(ls, 1);
646 if (error)
David Teigland23e8e1a2011-04-05 13:16:24 -0500647 goto out_recoverd;
David Teigland79d72b52007-05-18 09:02:20 -0500648
David Teigland8b0e7b22007-05-18 09:03:35 -0500649 wait_for_completion(&ls->ls_members_done);
650 error = ls->ls_members_result;
651 if (error)
652 goto out_members;
653
David Teigland79d72b52007-05-18 09:02:20 -0500654 dlm_create_debug_file(ls);
655
David Teigland075f0172014-02-14 11:54:44 -0600656 log_rinfo(ls, "join complete");
David Teiglande7fd4172006-01-18 09:30:29 +0000657 *lockspace = ls;
658 return 0;
659
David Teigland8b0e7b22007-05-18 09:03:35 -0500660 out_members:
661 do_uevent(ls, 0);
662 dlm_clear_members(ls);
663 kfree(ls->ls_node_array);
David Teigland23e8e1a2011-04-05 13:16:24 -0500664 out_recoverd:
David Teigland5f88f1e2006-08-24 14:47:20 -0500665 dlm_recoverd_stop(ls);
David Teigland23e8e1a2011-04-05 13:16:24 -0500666 out_callback:
667 dlm_callback_stop(ls);
David Teigland79d72b52007-05-18 09:02:20 -0500668 out_delist:
David Teiglande7fd4172006-01-18 09:30:29 +0000669 spin_lock(&lslist_lock);
670 list_del(&ls->ls_list);
671 spin_unlock(&lslist_lock);
David Teigland1d7c4842012-05-15 16:07:49 -0500672 idr_destroy(&ls->ls_recover_idr);
David Teiglande7fd4172006-01-18 09:30:29 +0000673 kfree(ls->ls_recover_buf);
David Teigland05c32f42012-06-14 12:17:32 -0500674 out_lkbidr:
David Teigland3d6aa672011-07-06 17:00:54 -0500675 idr_destroy(&ls->ls_lkbidr);
Vasily Averin5dbe8eb2018-11-15 13:15:05 +0300676 out_rsbtbl:
David Teigland05c32f42012-06-14 12:17:32 -0500677 for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
678 if (ls->ls_remove_names[i])
679 kfree(ls->ls_remove_names[i]);
680 }
Bryn M. Reevesc282af42011-07-01 15:49:23 -0500681 vfree(ls->ls_rsbtbl);
David Teiglande7fd4172006-01-18 09:30:29 +0000682 out_lsfree:
David Teigland79d72b52007-05-18 09:02:20 -0500683 if (do_unreg)
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800684 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500685 else
686 kfree(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000687 out:
688 module_put(THIS_MODULE);
689 return error;
690}
691
David Teigland60f98d12011-11-02 14:30:58 -0500692int dlm_new_lockspace(const char *name, const char *cluster,
693 uint32_t flags, int lvblen,
694 const struct dlm_lockspace_ops *ops, void *ops_arg,
695 int *ops_result, dlm_lockspace_t **lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000696{
697 int error = 0;
698
David Teigland90135922006-01-20 08:47:07 +0000699 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000700 if (!ls_count)
701 error = threads_start();
702 if (error)
703 goto out;
704
David Teigland60f98d12011-11-02 14:30:58 -0500705 error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg,
706 ops_result, lockspace);
David Teiglande7fd4172006-01-18 09:30:29 +0000707 if (!error)
708 ls_count++;
David Teigland8511a272009-04-08 15:38:43 -0500709 if (error > 0)
710 error = 0;
711 if (!ls_count)
David Teigland8b0e7b22007-05-18 09:03:35 -0500712 threads_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000713 out:
David Teigland90135922006-01-20 08:47:07 +0000714 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000715 return error;
716}
717
David Teigland3d6aa672011-07-06 17:00:54 -0500718static int lkb_idr_is_local(int id, void *p, void *data)
David Teiglande7fd4172006-01-18 09:30:29 +0000719{
David Teigland3d6aa672011-07-06 17:00:54 -0500720 struct dlm_lkb *lkb = p;
David Teiglande7fd4172006-01-18 09:30:29 +0000721
Bart Van Asschea97f4a62013-10-16 14:20:25 +0200722 return lkb->lkb_nodeid == 0 && lkb->lkb_grmode != DLM_LOCK_IV;
David Teigland3d6aa672011-07-06 17:00:54 -0500723}
David Teiglande7fd4172006-01-18 09:30:29 +0000724
David Teigland3d6aa672011-07-06 17:00:54 -0500725static int lkb_idr_is_any(int id, void *p, void *data)
726{
727 return 1;
728}
729
730static int lkb_idr_free(int id, void *p, void *data)
731{
732 struct dlm_lkb *lkb = p;
733
David Teigland3d6aa672011-07-06 17:00:54 -0500734 if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
735 dlm_free_lvb(lkb->lkb_lvbptr);
736
737 dlm_free_lkb(lkb);
738 return 0;
739}
740
741/* NOTE: We check the lkbidr here rather than the resource table.
742 This is because there may be LKBs queued as ASTs that have been unlinked
743 from their RSBs and are pending deletion once the AST has been delivered */
744
745static int lockspace_busy(struct dlm_ls *ls, int force)
746{
747 int rv;
748
749 spin_lock(&ls->ls_lkbidr_spin);
750 if (force == 0) {
751 rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls);
752 } else if (force == 1) {
753 rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls);
754 } else {
755 rv = 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000756 }
David Teigland3d6aa672011-07-06 17:00:54 -0500757 spin_unlock(&ls->ls_lkbidr_spin);
758 return rv;
David Teiglande7fd4172006-01-18 09:30:29 +0000759}
760
761static int release_lockspace(struct dlm_ls *ls, int force)
762{
David Teiglande7fd4172006-01-18 09:30:29 +0000763 struct dlm_rsb *rsb;
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500764 struct rb_node *n;
David Teigland0f8e0d92008-08-06 13:30:24 -0500765 int i, busy, rv;
David Teiglande7fd4172006-01-18 09:30:29 +0000766
David Teigland3d6aa672011-07-06 17:00:54 -0500767 busy = lockspace_busy(ls, force);
David Teigland0f8e0d92008-08-06 13:30:24 -0500768
769 spin_lock(&lslist_lock);
770 if (ls->ls_create_count == 1) {
David Teigland3d6aa672011-07-06 17:00:54 -0500771 if (busy) {
David Teigland0f8e0d92008-08-06 13:30:24 -0500772 rv = -EBUSY;
David Teigland3d6aa672011-07-06 17:00:54 -0500773 } else {
David Teigland0f8e0d92008-08-06 13:30:24 -0500774 /* remove_lockspace takes ls off lslist */
775 ls->ls_create_count = 0;
776 rv = 0;
777 }
778 } else if (ls->ls_create_count > 1) {
779 rv = --ls->ls_create_count;
780 } else {
781 rv = -EINVAL;
782 }
783 spin_unlock(&lslist_lock);
784
785 if (rv) {
786 log_debug(ls, "release_lockspace no remove %d", rv);
787 return rv;
788 }
789
790 dlm_device_deregister(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000791
David Teiglanddc68c7e2008-08-18 11:43:30 -0500792 if (force < 3 && dlm_user_daemon_available())
David Teiglande7fd4172006-01-18 09:30:29 +0000793 do_uevent(ls, 0);
794
795 dlm_recoverd_stop(ls);
796
David Teigland23e8e1a2011-04-05 13:16:24 -0500797 dlm_callback_stop(ls);
798
David Teiglande7fd4172006-01-18 09:30:29 +0000799 remove_lockspace(ls);
800
801 dlm_delete_debug_file(ls);
802
David Teigland72c9c042018-11-15 11:17:40 -0600803 idr_destroy(&ls->ls_recover_idr);
David Teiglande7fd4172006-01-18 09:30:29 +0000804 kfree(ls->ls_recover_buf);
805
806 /*
David Teigland3d6aa672011-07-06 17:00:54 -0500807 * Free all lkb's in idr
David Teiglande7fd4172006-01-18 09:30:29 +0000808 */
809
David Teigland3d6aa672011-07-06 17:00:54 -0500810 idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls);
David Teigland3d6aa672011-07-06 17:00:54 -0500811 idr_destroy(&ls->ls_lkbidr);
David Teiglande7fd4172006-01-18 09:30:29 +0000812
David Teiglande7fd4172006-01-18 09:30:29 +0000813 /*
814 * Free all rsb's on rsbtbl[] lists
815 */
816
817 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500818 while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) {
819 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
820 rb_erase(n, &ls->ls_rsbtbl[i].keep);
David Teigland52bda2b2007-11-07 09:06:49 -0600821 dlm_free_rsb(rsb);
David Teiglande7fd4172006-01-18 09:30:29 +0000822 }
823
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500824 while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) {
825 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
826 rb_erase(n, &ls->ls_rsbtbl[i].toss);
David Teigland52bda2b2007-11-07 09:06:49 -0600827 dlm_free_rsb(rsb);
David Teiglande7fd4172006-01-18 09:30:29 +0000828 }
829 }
830
Bryn M. Reevesc282af42011-07-01 15:49:23 -0500831 vfree(ls->ls_rsbtbl);
David Teiglande7fd4172006-01-18 09:30:29 +0000832
David Teigland05c32f42012-06-14 12:17:32 -0500833 for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++)
834 kfree(ls->ls_remove_names[i]);
835
David Teigland3881ac02011-07-07 14:05:03 -0500836 while (!list_empty(&ls->ls_new_rsb)) {
837 rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
838 res_hashchain);
839 list_del(&rsb->res_hashchain);
840 dlm_free_rsb(rsb);
841 }
842
David Teiglande7fd4172006-01-18 09:30:29 +0000843 /*
844 * Free structures on any other lists
845 */
846
David Teigland2896ee32006-11-27 11:31:22 -0600847 dlm_purge_requestqueue(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000848 kfree(ls->ls_recover_args);
David Teiglande7fd4172006-01-18 09:30:29 +0000849 dlm_clear_members(ls);
850 dlm_clear_members_gone(ls);
851 kfree(ls->ls_node_array);
David Teigland075f0172014-02-14 11:54:44 -0600852 log_rinfo(ls, "release_lockspace final free");
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800853 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500854 /* The ls structure will be freed when the kobject is done with */
David Teiglande7fd4172006-01-18 09:30:29 +0000855
David Teiglande7fd4172006-01-18 09:30:29 +0000856 module_put(THIS_MODULE);
857 return 0;
858}
859
860/*
861 * Called when a system has released all its locks and is not going to use the
862 * lockspace any longer. We free everything we're managing for this lockspace.
863 * Remaining nodes will go through the recovery process as if we'd died. The
864 * lockspace must continue to function as usual, participating in recoveries,
865 * until this returns.
866 *
867 * Force has 4 possible values:
868 * 0 - don't destroy locksapce if it has any LKBs
869 * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
870 * 2 - destroy lockspace regardless of LKBs
871 * 3 - destroy lockspace as part of a forced shutdown
872 */
873
874int dlm_release_lockspace(void *lockspace, int force)
875{
876 struct dlm_ls *ls;
David Teigland0f8e0d92008-08-06 13:30:24 -0500877 int error;
David Teiglande7fd4172006-01-18 09:30:29 +0000878
879 ls = dlm_find_lockspace_local(lockspace);
880 if (!ls)
881 return -EINVAL;
882 dlm_put_lockspace(ls);
David Teigland0f8e0d92008-08-06 13:30:24 -0500883
884 mutex_lock(&ls_lock);
885 error = release_lockspace(ls, force);
886 if (!error)
887 ls_count--;
David Teigland278afcb2008-11-13 13:22:34 -0600888 if (!ls_count)
David Teigland0f8e0d92008-08-06 13:30:24 -0500889 threads_stop();
890 mutex_unlock(&ls_lock);
891
892 return error;
David Teiglande7fd4172006-01-18 09:30:29 +0000893}
894
David Teiglanddc68c7e2008-08-18 11:43:30 -0500895void dlm_stop_lockspaces(void)
896{
897 struct dlm_ls *ls;
David Teigland696b3d82013-06-25 12:48:01 -0500898 int count;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500899
900 restart:
David Teigland696b3d82013-06-25 12:48:01 -0500901 count = 0;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500902 spin_lock(&lslist_lock);
903 list_for_each_entry(ls, &lslist, ls_list) {
David Teigland696b3d82013-06-25 12:48:01 -0500904 if (!test_bit(LSFL_RUNNING, &ls->ls_flags)) {
905 count++;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500906 continue;
David Teigland696b3d82013-06-25 12:48:01 -0500907 }
David Teiglanddc68c7e2008-08-18 11:43:30 -0500908 spin_unlock(&lslist_lock);
909 log_error(ls, "no userland control daemon, stopping lockspace");
910 dlm_ls_stop(ls);
911 goto restart;
912 }
913 spin_unlock(&lslist_lock);
David Teigland696b3d82013-06-25 12:48:01 -0500914
915 if (count)
916 log_print("dlm user daemon left %d lockspaces", count);
David Teiglanddc68c7e2008-08-18 11:43:30 -0500917}
918