blob: 5c108c49cb8cd30128d533630cdd3ac72810839d [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 Teiglandef0c2bb2007-03-28 09:56:46 -05005** Copyright (C) 2004-2007 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"
18#include "ast.h"
19#include "dir.h"
20#include "lowcomms.h"
21#include "config.h"
22#include "memory.h"
23#include "lock.h"
David Teiglandc56b39c2006-04-28 10:51:53 -040024#include "recover.h"
David Teigland2896ee32006-11-27 11:31:22 -060025#include "requestqueue.h"
David Teiglande7fd4172006-01-18 09:30:29 +000026
27#ifdef CONFIG_DLM_DEBUG
28int dlm_create_debug_file(struct dlm_ls *ls);
29void dlm_delete_debug_file(struct dlm_ls *ls);
30#else
31static inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; }
32static inline void dlm_delete_debug_file(struct dlm_ls *ls) { }
33#endif
34
35static int ls_count;
David Teigland90135922006-01-20 08:47:07 +000036static struct mutex ls_lock;
David Teiglande7fd4172006-01-18 09:30:29 +000037static struct list_head lslist;
38static spinlock_t lslist_lock;
39static struct task_struct * scand_task;
40
41
42static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
43{
44 ssize_t ret = len;
45 int n = simple_strtol(buf, NULL, 0);
46
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000047 ls = dlm_find_lockspace_local(ls->ls_local_handle);
48 if (!ls)
49 return -EINVAL;
50
David Teiglande7fd4172006-01-18 09:30:29 +000051 switch (n) {
52 case 0:
53 dlm_ls_stop(ls);
54 break;
55 case 1:
56 dlm_ls_start(ls);
57 break;
58 default:
59 ret = -EINVAL;
60 }
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000061 dlm_put_lockspace(ls);
David Teiglande7fd4172006-01-18 09:30:29 +000062 return ret;
63}
64
65static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
66{
67 ls->ls_uevent_result = simple_strtol(buf, NULL, 0);
68 set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
69 wake_up(&ls->ls_uevent_wait);
70 return len;
71}
72
73static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
74{
David Teiglanda1d144c2006-09-06 17:01:40 -050075 return snprintf(buf, PAGE_SIZE, "%u\n", ls->ls_global_id);
David Teiglande7fd4172006-01-18 09:30:29 +000076}
77
78static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
79{
80 ls->ls_global_id = simple_strtoul(buf, NULL, 0);
81 return len;
82}
83
David Teiglandc56b39c2006-04-28 10:51:53 -040084static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
85{
86 uint32_t status = dlm_recover_status(ls);
David Teiglanda1d144c2006-09-06 17:01:40 -050087 return snprintf(buf, PAGE_SIZE, "%x\n", status);
David Teiglandc56b39c2006-04-28 10:51:53 -040088}
89
David Teiglandfaa0f262006-08-08 17:08:42 -050090static ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf)
91{
David Teiglanda1d144c2006-09-06 17:01:40 -050092 return snprintf(buf, PAGE_SIZE, "%d\n", ls->ls_recover_nodeid);
David Teiglandfaa0f262006-08-08 17:08:42 -050093}
94
David Teiglande7fd4172006-01-18 09:30:29 +000095struct dlm_attr {
96 struct attribute attr;
97 ssize_t (*show)(struct dlm_ls *, char *);
98 ssize_t (*store)(struct dlm_ls *, const char *, size_t);
99};
100
101static struct dlm_attr dlm_attr_control = {
102 .attr = {.name = "control", .mode = S_IWUSR},
103 .store = dlm_control_store
104};
105
106static struct dlm_attr dlm_attr_event = {
107 .attr = {.name = "event_done", .mode = S_IWUSR},
108 .store = dlm_event_store
109};
110
111static struct dlm_attr dlm_attr_id = {
112 .attr = {.name = "id", .mode = S_IRUGO | S_IWUSR},
113 .show = dlm_id_show,
114 .store = dlm_id_store
115};
116
David Teiglandc56b39c2006-04-28 10:51:53 -0400117static struct dlm_attr dlm_attr_recover_status = {
118 .attr = {.name = "recover_status", .mode = S_IRUGO},
119 .show = dlm_recover_status_show
120};
121
David Teiglandfaa0f262006-08-08 17:08:42 -0500122static struct dlm_attr dlm_attr_recover_nodeid = {
123 .attr = {.name = "recover_nodeid", .mode = S_IRUGO},
124 .show = dlm_recover_nodeid_show
125};
126
David Teiglande7fd4172006-01-18 09:30:29 +0000127static struct attribute *dlm_attrs[] = {
128 &dlm_attr_control.attr,
129 &dlm_attr_event.attr,
130 &dlm_attr_id.attr,
David Teiglandc56b39c2006-04-28 10:51:53 -0400131 &dlm_attr_recover_status.attr,
David Teiglandfaa0f262006-08-08 17:08:42 -0500132 &dlm_attr_recover_nodeid.attr,
David Teiglande7fd4172006-01-18 09:30:29 +0000133 NULL,
134};
135
136static ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr,
137 char *buf)
138{
139 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
140 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
141 return a->show ? a->show(ls, buf) : 0;
142}
143
144static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
145 const char *buf, size_t len)
146{
147 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
148 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
149 return a->store ? a->store(ls, buf, len) : len;
150}
151
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000152static void lockspace_kobj_release(struct kobject *k)
153{
154 struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj);
155 kfree(ls);
156}
157
David Teiglande7fd4172006-01-18 09:30:29 +0000158static struct sysfs_ops dlm_attr_ops = {
159 .show = dlm_attr_show,
160 .store = dlm_attr_store,
161};
162
163static struct kobj_type dlm_ktype = {
164 .default_attrs = dlm_attrs,
165 .sysfs_ops = &dlm_attr_ops,
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000166 .release = lockspace_kobj_release,
David Teiglande7fd4172006-01-18 09:30:29 +0000167};
168
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100169static struct kset *dlm_kset;
David Teiglande7fd4172006-01-18 09:30:29 +0000170
David Teiglande7fd4172006-01-18 09:30:29 +0000171static int do_uevent(struct dlm_ls *ls, int in)
172{
173 int error;
174
175 if (in)
176 kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
177 else
178 kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
179
David Teigland8b0e7b22007-05-18 09:03:35 -0500180 log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
181
182 /* dlm_controld will see the uevent, do the necessary group management
183 and then write to sysfs to wake us */
184
David Teiglande7fd4172006-01-18 09:30:29 +0000185 error = wait_event_interruptible(ls->ls_uevent_wait,
186 test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
David Teigland8b0e7b22007-05-18 09:03:35 -0500187
188 log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
189
David Teiglande7fd4172006-01-18 09:30:29 +0000190 if (error)
191 goto out;
192
193 error = ls->ls_uevent_result;
194 out:
David Teigland8b0e7b22007-05-18 09:03:35 -0500195 if (error)
196 log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
197 error, ls->ls_uevent_result);
David Teiglande7fd4172006-01-18 09:30:29 +0000198 return error;
199}
200
201
202int dlm_lockspace_init(void)
203{
David Teiglande7fd4172006-01-18 09:30:29 +0000204 ls_count = 0;
David Teigland90135922006-01-20 08:47:07 +0000205 mutex_init(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000206 INIT_LIST_HEAD(&lslist);
207 spin_lock_init(&lslist_lock);
208
Greg Kroah-Hartman0ff21e42007-11-06 10:36:58 -0800209 dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100210 if (!dlm_kset) {
211 printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
212 return -ENOMEM;
213 }
214 return 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000215}
216
217void dlm_lockspace_exit(void)
218{
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100219 kset_unregister(dlm_kset);
David Teiglande7fd4172006-01-18 09:30:29 +0000220}
221
222static int dlm_scand(void *data)
223{
224 struct dlm_ls *ls;
225
226 while (!kthread_should_stop()) {
David Teigland85e86ed2007-05-18 08:58:15 -0500227 list_for_each_entry(ls, &lslist, ls_list) {
228 if (dlm_lock_recovery_try(ls)) {
229 dlm_scan_rsbs(ls);
David Teigland3ae1acf2007-05-18 08:59:31 -0500230 dlm_scan_timeout(ls);
David Teigland85e86ed2007-05-18 08:58:15 -0500231 dlm_unlock_recovery(ls);
232 }
233 }
David Teigland68c817a2007-01-09 09:41:48 -0600234 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
David Teiglande7fd4172006-01-18 09:30:29 +0000235 }
236 return 0;
237}
238
239static int dlm_scand_start(void)
240{
241 struct task_struct *p;
242 int error = 0;
243
244 p = kthread_run(dlm_scand, NULL, "dlm_scand");
245 if (IS_ERR(p))
246 error = PTR_ERR(p);
247 else
248 scand_task = p;
249 return error;
250}
251
252static void dlm_scand_stop(void)
253{
254 kthread_stop(scand_task);
255}
256
257static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
258{
259 struct dlm_ls *ls;
260
261 spin_lock(&lslist_lock);
262
263 list_for_each_entry(ls, &lslist, ls_list) {
264 if (ls->ls_namelen == namelen &&
265 memcmp(ls->ls_name, name, namelen) == 0)
266 goto out;
267 }
268 ls = NULL;
269 out:
270 spin_unlock(&lslist_lock);
271 return ls;
272}
273
274struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
275{
276 struct dlm_ls *ls;
277
278 spin_lock(&lslist_lock);
279
280 list_for_each_entry(ls, &lslist, ls_list) {
281 if (ls->ls_global_id == id) {
282 ls->ls_count++;
283 goto out;
284 }
285 }
286 ls = NULL;
287 out:
288 spin_unlock(&lslist_lock);
289 return ls;
290}
291
David Teigland597d0ca2006-07-12 16:44:04 -0500292struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000293{
David Teigland597d0ca2006-07-12 16:44:04 -0500294 struct dlm_ls *ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000295
296 spin_lock(&lslist_lock);
David Teigland597d0ca2006-07-12 16:44:04 -0500297 list_for_each_entry(ls, &lslist, ls_list) {
298 if (ls->ls_local_handle == lockspace) {
299 ls->ls_count++;
300 goto out;
301 }
302 }
303 ls = NULL;
304 out:
305 spin_unlock(&lslist_lock);
306 return ls;
307}
308
309struct dlm_ls *dlm_find_lockspace_device(int minor)
310{
311 struct dlm_ls *ls;
312
313 spin_lock(&lslist_lock);
314 list_for_each_entry(ls, &lslist, ls_list) {
315 if (ls->ls_device.minor == minor) {
316 ls->ls_count++;
317 goto out;
318 }
319 }
320 ls = NULL;
321 out:
David Teiglande7fd4172006-01-18 09:30:29 +0000322 spin_unlock(&lslist_lock);
323 return ls;
324}
325
326void dlm_put_lockspace(struct dlm_ls *ls)
327{
328 spin_lock(&lslist_lock);
329 ls->ls_count--;
330 spin_unlock(&lslist_lock);
331}
332
333static void remove_lockspace(struct dlm_ls *ls)
334{
335 for (;;) {
336 spin_lock(&lslist_lock);
337 if (ls->ls_count == 0) {
338 list_del(&ls->ls_list);
339 spin_unlock(&lslist_lock);
340 return;
341 }
342 spin_unlock(&lslist_lock);
343 ssleep(1);
344 }
345}
346
347static int threads_start(void)
348{
349 int error;
350
351 /* Thread which process lock requests for all lockspace's */
352 error = dlm_astd_start();
353 if (error) {
354 log_print("cannot start dlm_astd thread %d", error);
355 goto fail;
356 }
357
358 error = dlm_scand_start();
359 if (error) {
360 log_print("cannot start dlm_scand thread %d", error);
361 goto astd_fail;
362 }
363
364 /* Thread for sending/receiving messages for all lockspace's */
365 error = dlm_lowcomms_start();
366 if (error) {
367 log_print("cannot start dlm lowcomms %d", error);
368 goto scand_fail;
369 }
370
371 return 0;
372
373 scand_fail:
374 dlm_scand_stop();
375 astd_fail:
376 dlm_astd_stop();
377 fail:
378 return error;
379}
380
381static void threads_stop(void)
382{
383 dlm_scand_stop();
384 dlm_lowcomms_stop();
385 dlm_astd_stop();
386}
387
388static int new_lockspace(char *name, int namelen, void **lockspace,
389 uint32_t flags, int lvblen)
390{
391 struct dlm_ls *ls;
392 int i, size, error = -ENOMEM;
David Teigland79d72b52007-05-18 09:02:20 -0500393 int do_unreg = 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000394
395 if (namelen > DLM_LOCKSPACE_LEN)
396 return -EINVAL;
397
398 if (!lvblen || (lvblen % 8))
399 return -EINVAL;
400
401 if (!try_module_get(THIS_MODULE))
402 return -EINVAL;
403
404 ls = dlm_find_lockspace_name(name, namelen);
405 if (ls) {
406 *lockspace = ls;
407 module_put(THIS_MODULE);
408 return -EEXIST;
409 }
410
David Teigland90135922006-01-20 08:47:07 +0000411 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000412 if (!ls)
413 goto out;
David Teiglande7fd4172006-01-18 09:30:29 +0000414 memcpy(ls->ls_name, name, namelen);
415 ls->ls_namelen = namelen;
David Teiglande7fd4172006-01-18 09:30:29 +0000416 ls->ls_lvblen = lvblen;
417 ls->ls_count = 0;
418 ls->ls_flags = 0;
419
David Teigland3ae1acf2007-05-18 08:59:31 -0500420 if (flags & DLM_LSFL_TIMEWARN)
421 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
David Teigland3ae1acf2007-05-18 08:59:31 -0500422
Patrick Caulfield44f487a2007-06-06 09:21:22 -0500423 if (flags & DLM_LSFL_FS)
424 ls->ls_allocation = GFP_NOFS;
425 else
426 ls->ls_allocation = GFP_KERNEL;
427
David Teiglandfad59c12007-06-11 10:47:18 -0500428 /* ls_exflags are forced to match among nodes, and we don't
429 need to require all nodes to have TIMEWARN or FS set */
430 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
431
David Teigland68c817a2007-01-09 09:41:48 -0600432 size = dlm_config.ci_rsbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000433 ls->ls_rsbtbl_size = size;
434
435 ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL);
436 if (!ls->ls_rsbtbl)
437 goto out_lsfree;
438 for (i = 0; i < size; i++) {
439 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list);
440 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss);
441 rwlock_init(&ls->ls_rsbtbl[i].lock);
442 }
443
David Teigland68c817a2007-01-09 09:41:48 -0600444 size = dlm_config.ci_lkbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000445 ls->ls_lkbtbl_size = size;
446
447 ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL);
448 if (!ls->ls_lkbtbl)
449 goto out_rsbfree;
450 for (i = 0; i < size; i++) {
451 INIT_LIST_HEAD(&ls->ls_lkbtbl[i].list);
452 rwlock_init(&ls->ls_lkbtbl[i].lock);
453 ls->ls_lkbtbl[i].counter = 1;
454 }
455
David Teigland68c817a2007-01-09 09:41:48 -0600456 size = dlm_config.ci_dirtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000457 ls->ls_dirtbl_size = size;
458
459 ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL);
460 if (!ls->ls_dirtbl)
461 goto out_lkbfree;
462 for (i = 0; i < size; i++) {
463 INIT_LIST_HEAD(&ls->ls_dirtbl[i].list);
464 rwlock_init(&ls->ls_dirtbl[i].lock);
465 }
466
467 INIT_LIST_HEAD(&ls->ls_waiters);
David Teigland90135922006-01-20 08:47:07 +0000468 mutex_init(&ls->ls_waiters_mutex);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500469 INIT_LIST_HEAD(&ls->ls_orphans);
470 mutex_init(&ls->ls_orphans_mutex);
David Teigland3ae1acf2007-05-18 08:59:31 -0500471 INIT_LIST_HEAD(&ls->ls_timeout);
472 mutex_init(&ls->ls_timeout_mutex);
David Teiglande7fd4172006-01-18 09:30:29 +0000473
474 INIT_LIST_HEAD(&ls->ls_nodes);
475 INIT_LIST_HEAD(&ls->ls_nodes_gone);
476 ls->ls_num_nodes = 0;
477 ls->ls_low_nodeid = 0;
478 ls->ls_total_weight = 0;
479 ls->ls_node_array = NULL;
480
481 memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
482 ls->ls_stub_rsb.res_ls = ls;
483
David Teigland5de63192006-07-25 13:44:31 -0500484 ls->ls_debug_rsb_dentry = NULL;
485 ls->ls_debug_waiters_dentry = NULL;
David Teiglande7fd4172006-01-18 09:30:29 +0000486
487 init_waitqueue_head(&ls->ls_uevent_wait);
488 ls->ls_uevent_result = 0;
David Teigland8b0e7b22007-05-18 09:03:35 -0500489 init_completion(&ls->ls_members_done);
490 ls->ls_members_result = -1;
David Teiglande7fd4172006-01-18 09:30:29 +0000491
492 ls->ls_recoverd_task = NULL;
David Teigland90135922006-01-20 08:47:07 +0000493 mutex_init(&ls->ls_recoverd_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000494 spin_lock_init(&ls->ls_recover_lock);
David Teigland98f176f2006-11-27 13:19:28 -0600495 spin_lock_init(&ls->ls_rcom_spin);
496 get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
David Teiglande7fd4172006-01-18 09:30:29 +0000497 ls->ls_recover_status = 0;
498 ls->ls_recover_seq = 0;
499 ls->ls_recover_args = NULL;
500 init_rwsem(&ls->ls_in_recovery);
David Teiglandc36258b2007-09-27 15:53:38 -0500501 init_rwsem(&ls->ls_recv_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000502 INIT_LIST_HEAD(&ls->ls_requestqueue);
David Teigland90135922006-01-20 08:47:07 +0000503 mutex_init(&ls->ls_requestqueue_mutex);
David Teigland597d0ca2006-07-12 16:44:04 -0500504 mutex_init(&ls->ls_clear_proc_locks);
David Teiglande7fd4172006-01-18 09:30:29 +0000505
David Teigland68c817a2007-01-09 09:41:48 -0600506 ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000507 if (!ls->ls_recover_buf)
508 goto out_dirfree;
509
510 INIT_LIST_HEAD(&ls->ls_recover_list);
511 spin_lock_init(&ls->ls_recover_list_lock);
512 ls->ls_recover_list_count = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500513 ls->ls_local_handle = ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000514 init_waitqueue_head(&ls->ls_wait_general);
515 INIT_LIST_HEAD(&ls->ls_root_list);
516 init_rwsem(&ls->ls_root_sem);
517
518 down_write(&ls->ls_in_recovery);
519
David Teigland5f88f1e2006-08-24 14:47:20 -0500520 spin_lock(&lslist_lock);
521 list_add(&ls->ls_list, &lslist);
522 spin_unlock(&lslist_lock);
523
524 /* needs to find ls in lslist */
David Teiglande7fd4172006-01-18 09:30:29 +0000525 error = dlm_recoverd_start(ls);
526 if (error) {
527 log_error(ls, "can't start dlm_recoverd %d", error);
David Teigland79d72b52007-05-18 09:02:20 -0500528 goto out_delist;
David Teiglande7fd4172006-01-18 09:30:29 +0000529 }
530
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400531 ls->ls_kobj.kset = dlm_kset;
532 error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
533 "%s", ls->ls_name);
David Teiglande7fd4172006-01-18 09:30:29 +0000534 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500535 goto out_stop;
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400536 kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
David Teigland79d72b52007-05-18 09:02:20 -0500537
538 /* let kobject handle freeing of ls if there's an error */
539 do_unreg = 1;
David Teiglande7fd4172006-01-18 09:30:29 +0000540
David Teigland8b0e7b22007-05-18 09:03:35 -0500541 /* This uevent triggers dlm_controld in userspace to add us to the
542 group of nodes that are members of this lockspace (managed by the
543 cluster infrastructure.) Once it's done that, it tells us who the
544 current lockspace members are (via configfs) and then tells the
545 lockspace to start running (via sysfs) in dlm_ls_start(). */
546
David Teiglande7fd4172006-01-18 09:30:29 +0000547 error = do_uevent(ls, 1);
548 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500549 goto out_stop;
550
David Teigland8b0e7b22007-05-18 09:03:35 -0500551 wait_for_completion(&ls->ls_members_done);
552 error = ls->ls_members_result;
553 if (error)
554 goto out_members;
555
David Teigland79d72b52007-05-18 09:02:20 -0500556 dlm_create_debug_file(ls);
557
558 log_debug(ls, "join complete");
David Teiglande7fd4172006-01-18 09:30:29 +0000559
560 *lockspace = ls;
561 return 0;
562
David Teigland8b0e7b22007-05-18 09:03:35 -0500563 out_members:
564 do_uevent(ls, 0);
565 dlm_clear_members(ls);
566 kfree(ls->ls_node_array);
David Teigland79d72b52007-05-18 09:02:20 -0500567 out_stop:
David Teigland5f88f1e2006-08-24 14:47:20 -0500568 dlm_recoverd_stop(ls);
David Teigland79d72b52007-05-18 09:02:20 -0500569 out_delist:
David Teiglande7fd4172006-01-18 09:30:29 +0000570 spin_lock(&lslist_lock);
571 list_del(&ls->ls_list);
572 spin_unlock(&lslist_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000573 kfree(ls->ls_recover_buf);
574 out_dirfree:
575 kfree(ls->ls_dirtbl);
576 out_lkbfree:
577 kfree(ls->ls_lkbtbl);
578 out_rsbfree:
579 kfree(ls->ls_rsbtbl);
580 out_lsfree:
David Teigland79d72b52007-05-18 09:02:20 -0500581 if (do_unreg)
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800582 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500583 else
584 kfree(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000585 out:
586 module_put(THIS_MODULE);
587 return error;
588}
589
590int dlm_new_lockspace(char *name, int namelen, void **lockspace,
591 uint32_t flags, int lvblen)
592{
593 int error = 0;
594
David Teigland90135922006-01-20 08:47:07 +0000595 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000596 if (!ls_count)
597 error = threads_start();
598 if (error)
599 goto out;
600
601 error = new_lockspace(name, namelen, lockspace, flags, lvblen);
602 if (!error)
603 ls_count++;
David Teigland8b0e7b22007-05-18 09:03:35 -0500604 else if (!ls_count)
605 threads_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000606 out:
David Teigland90135922006-01-20 08:47:07 +0000607 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000608 return error;
609}
610
611/* Return 1 if the lockspace still has active remote locks,
612 * 2 if the lockspace still has active local locks.
613 */
614static int lockspace_busy(struct dlm_ls *ls)
615{
616 int i, lkb_found = 0;
617 struct dlm_lkb *lkb;
618
619 /* NOTE: We check the lockidtbl here rather than the resource table.
620 This is because there may be LKBs queued as ASTs that have been
621 unlinked from their RSBs and are pending deletion once the AST has
622 been delivered */
623
624 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
625 read_lock(&ls->ls_lkbtbl[i].lock);
626 if (!list_empty(&ls->ls_lkbtbl[i].list)) {
627 lkb_found = 1;
628 list_for_each_entry(lkb, &ls->ls_lkbtbl[i].list,
629 lkb_idtbl_list) {
630 if (!lkb->lkb_nodeid) {
631 read_unlock(&ls->ls_lkbtbl[i].lock);
632 return 2;
633 }
634 }
635 }
636 read_unlock(&ls->ls_lkbtbl[i].lock);
637 }
638 return lkb_found;
639}
640
641static int release_lockspace(struct dlm_ls *ls, int force)
642{
643 struct dlm_lkb *lkb;
644 struct dlm_rsb *rsb;
645 struct list_head *head;
646 int i;
647 int busy = lockspace_busy(ls);
648
649 if (busy > force)
650 return -EBUSY;
651
652 if (force < 3)
653 do_uevent(ls, 0);
654
655 dlm_recoverd_stop(ls);
656
657 remove_lockspace(ls);
658
659 dlm_delete_debug_file(ls);
660
661 dlm_astd_suspend();
662
663 kfree(ls->ls_recover_buf);
664
665 /*
666 * Free direntry structs.
667 */
668
669 dlm_dir_clear(ls);
670 kfree(ls->ls_dirtbl);
671
672 /*
673 * Free all lkb's on lkbtbl[] lists.
674 */
675
676 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
677 head = &ls->ls_lkbtbl[i].list;
678 while (!list_empty(head)) {
679 lkb = list_entry(head->next, struct dlm_lkb,
680 lkb_idtbl_list);
681
682 list_del(&lkb->lkb_idtbl_list);
683
684 dlm_del_ast(lkb);
685
686 if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
687 free_lvb(lkb->lkb_lvbptr);
688
689 free_lkb(lkb);
690 }
691 }
692 dlm_astd_resume();
693
694 kfree(ls->ls_lkbtbl);
695
696 /*
697 * Free all rsb's on rsbtbl[] lists
698 */
699
700 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
701 head = &ls->ls_rsbtbl[i].list;
702 while (!list_empty(head)) {
703 rsb = list_entry(head->next, struct dlm_rsb,
704 res_hashchain);
705
706 list_del(&rsb->res_hashchain);
707 free_rsb(rsb);
708 }
709
710 head = &ls->ls_rsbtbl[i].toss;
711 while (!list_empty(head)) {
712 rsb = list_entry(head->next, struct dlm_rsb,
713 res_hashchain);
714 list_del(&rsb->res_hashchain);
715 free_rsb(rsb);
716 }
717 }
718
719 kfree(ls->ls_rsbtbl);
720
721 /*
722 * Free structures on any other lists
723 */
724
David Teigland2896ee32006-11-27 11:31:22 -0600725 dlm_purge_requestqueue(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000726 kfree(ls->ls_recover_args);
727 dlm_clear_free_entries(ls);
728 dlm_clear_members(ls);
729 dlm_clear_members_gone(ls);
730 kfree(ls->ls_node_array);
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800731 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500732 /* The ls structure will be freed when the kobject is done with */
David Teiglande7fd4172006-01-18 09:30:29 +0000733
David Teigland90135922006-01-20 08:47:07 +0000734 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000735 ls_count--;
736 if (!ls_count)
737 threads_stop();
David Teigland90135922006-01-20 08:47:07 +0000738 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000739
740 module_put(THIS_MODULE);
741 return 0;
742}
743
744/*
745 * Called when a system has released all its locks and is not going to use the
746 * lockspace any longer. We free everything we're managing for this lockspace.
747 * Remaining nodes will go through the recovery process as if we'd died. The
748 * lockspace must continue to function as usual, participating in recoveries,
749 * until this returns.
750 *
751 * Force has 4 possible values:
752 * 0 - don't destroy locksapce if it has any LKBs
753 * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
754 * 2 - destroy lockspace regardless of LKBs
755 * 3 - destroy lockspace as part of a forced shutdown
756 */
757
758int dlm_release_lockspace(void *lockspace, int force)
759{
760 struct dlm_ls *ls;
761
762 ls = dlm_find_lockspace_local(lockspace);
763 if (!ls)
764 return -EINVAL;
765 dlm_put_lockspace(ls);
766 return release_lockspace(ls, force);
767}
768