blob: e64b0dc664f3fb52a7011b8edaad06368efdc8ee [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
171static int kobject_setup(struct dlm_ls *ls)
172{
173 char lsname[DLM_LOCKSPACE_LEN];
174 int error;
175
176 memset(lsname, 0, DLM_LOCKSPACE_LEN);
177 snprintf(lsname, DLM_LOCKSPACE_LEN, "%s", ls->ls_name);
178
179 error = kobject_set_name(&ls->ls_kobj, "%s", lsname);
180 if (error)
181 return error;
182
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100183 ls->ls_kobj.kset = dlm_kset;
David Teiglande7fd4172006-01-18 09:30:29 +0000184 ls->ls_kobj.ktype = &dlm_ktype;
185 return 0;
186}
187
188static int do_uevent(struct dlm_ls *ls, int in)
189{
190 int error;
191
192 if (in)
193 kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
194 else
195 kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
196
David Teigland8b0e7b22007-05-18 09:03:35 -0500197 log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
198
199 /* dlm_controld will see the uevent, do the necessary group management
200 and then write to sysfs to wake us */
201
David Teiglande7fd4172006-01-18 09:30:29 +0000202 error = wait_event_interruptible(ls->ls_uevent_wait,
203 test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
David Teigland8b0e7b22007-05-18 09:03:35 -0500204
205 log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
206
David Teiglande7fd4172006-01-18 09:30:29 +0000207 if (error)
208 goto out;
209
210 error = ls->ls_uevent_result;
211 out:
David Teigland8b0e7b22007-05-18 09:03:35 -0500212 if (error)
213 log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
214 error, ls->ls_uevent_result);
David Teiglande7fd4172006-01-18 09:30:29 +0000215 return error;
216}
217
218
219int dlm_lockspace_init(void)
220{
David Teiglande7fd4172006-01-18 09:30:29 +0000221 ls_count = 0;
David Teigland90135922006-01-20 08:47:07 +0000222 mutex_init(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000223 INIT_LIST_HEAD(&lslist);
224 spin_lock_init(&lslist_lock);
225
Greg Kroah-Hartman0ff21e42007-11-06 10:36:58 -0800226 dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100227 if (!dlm_kset) {
228 printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
229 return -ENOMEM;
230 }
231 return 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000232}
233
234void dlm_lockspace_exit(void)
235{
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100236 kset_unregister(dlm_kset);
David Teiglande7fd4172006-01-18 09:30:29 +0000237}
238
239static int dlm_scand(void *data)
240{
241 struct dlm_ls *ls;
242
243 while (!kthread_should_stop()) {
David Teigland85e86ed2007-05-18 08:58:15 -0500244 list_for_each_entry(ls, &lslist, ls_list) {
245 if (dlm_lock_recovery_try(ls)) {
246 dlm_scan_rsbs(ls);
David Teigland3ae1acf2007-05-18 08:59:31 -0500247 dlm_scan_timeout(ls);
David Teigland85e86ed2007-05-18 08:58:15 -0500248 dlm_unlock_recovery(ls);
249 }
250 }
David Teigland68c817a2007-01-09 09:41:48 -0600251 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
David Teiglande7fd4172006-01-18 09:30:29 +0000252 }
253 return 0;
254}
255
256static int dlm_scand_start(void)
257{
258 struct task_struct *p;
259 int error = 0;
260
261 p = kthread_run(dlm_scand, NULL, "dlm_scand");
262 if (IS_ERR(p))
263 error = PTR_ERR(p);
264 else
265 scand_task = p;
266 return error;
267}
268
269static void dlm_scand_stop(void)
270{
271 kthread_stop(scand_task);
272}
273
274static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
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_namelen == namelen &&
282 memcmp(ls->ls_name, name, namelen) == 0)
283 goto out;
284 }
285 ls = NULL;
286 out:
287 spin_unlock(&lslist_lock);
288 return ls;
289}
290
291struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
292{
293 struct dlm_ls *ls;
294
295 spin_lock(&lslist_lock);
296
297 list_for_each_entry(ls, &lslist, ls_list) {
298 if (ls->ls_global_id == id) {
299 ls->ls_count++;
300 goto out;
301 }
302 }
303 ls = NULL;
304 out:
305 spin_unlock(&lslist_lock);
306 return ls;
307}
308
David Teigland597d0ca2006-07-12 16:44:04 -0500309struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000310{
David Teigland597d0ca2006-07-12 16:44:04 -0500311 struct dlm_ls *ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000312
313 spin_lock(&lslist_lock);
David Teigland597d0ca2006-07-12 16:44:04 -0500314 list_for_each_entry(ls, &lslist, ls_list) {
315 if (ls->ls_local_handle == lockspace) {
316 ls->ls_count++;
317 goto out;
318 }
319 }
320 ls = NULL;
321 out:
322 spin_unlock(&lslist_lock);
323 return ls;
324}
325
326struct dlm_ls *dlm_find_lockspace_device(int minor)
327{
328 struct dlm_ls *ls;
329
330 spin_lock(&lslist_lock);
331 list_for_each_entry(ls, &lslist, ls_list) {
332 if (ls->ls_device.minor == minor) {
333 ls->ls_count++;
334 goto out;
335 }
336 }
337 ls = NULL;
338 out:
David Teiglande7fd4172006-01-18 09:30:29 +0000339 spin_unlock(&lslist_lock);
340 return ls;
341}
342
343void dlm_put_lockspace(struct dlm_ls *ls)
344{
345 spin_lock(&lslist_lock);
346 ls->ls_count--;
347 spin_unlock(&lslist_lock);
348}
349
350static void remove_lockspace(struct dlm_ls *ls)
351{
352 for (;;) {
353 spin_lock(&lslist_lock);
354 if (ls->ls_count == 0) {
355 list_del(&ls->ls_list);
356 spin_unlock(&lslist_lock);
357 return;
358 }
359 spin_unlock(&lslist_lock);
360 ssleep(1);
361 }
362}
363
364static int threads_start(void)
365{
366 int error;
367
368 /* Thread which process lock requests for all lockspace's */
369 error = dlm_astd_start();
370 if (error) {
371 log_print("cannot start dlm_astd thread %d", error);
372 goto fail;
373 }
374
375 error = dlm_scand_start();
376 if (error) {
377 log_print("cannot start dlm_scand thread %d", error);
378 goto astd_fail;
379 }
380
381 /* Thread for sending/receiving messages for all lockspace's */
382 error = dlm_lowcomms_start();
383 if (error) {
384 log_print("cannot start dlm lowcomms %d", error);
385 goto scand_fail;
386 }
387
388 return 0;
389
390 scand_fail:
391 dlm_scand_stop();
392 astd_fail:
393 dlm_astd_stop();
394 fail:
395 return error;
396}
397
398static void threads_stop(void)
399{
400 dlm_scand_stop();
401 dlm_lowcomms_stop();
402 dlm_astd_stop();
403}
404
405static int new_lockspace(char *name, int namelen, void **lockspace,
406 uint32_t flags, int lvblen)
407{
408 struct dlm_ls *ls;
409 int i, size, error = -ENOMEM;
David Teigland79d72b52007-05-18 09:02:20 -0500410 int do_unreg = 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000411
412 if (namelen > DLM_LOCKSPACE_LEN)
413 return -EINVAL;
414
415 if (!lvblen || (lvblen % 8))
416 return -EINVAL;
417
418 if (!try_module_get(THIS_MODULE))
419 return -EINVAL;
420
421 ls = dlm_find_lockspace_name(name, namelen);
422 if (ls) {
423 *lockspace = ls;
424 module_put(THIS_MODULE);
425 return -EEXIST;
426 }
427
David Teigland90135922006-01-20 08:47:07 +0000428 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000429 if (!ls)
430 goto out;
David Teiglande7fd4172006-01-18 09:30:29 +0000431 memcpy(ls->ls_name, name, namelen);
432 ls->ls_namelen = namelen;
David Teiglande7fd4172006-01-18 09:30:29 +0000433 ls->ls_lvblen = lvblen;
434 ls->ls_count = 0;
435 ls->ls_flags = 0;
436
David Teigland3ae1acf2007-05-18 08:59:31 -0500437 if (flags & DLM_LSFL_TIMEWARN)
438 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
David Teigland3ae1acf2007-05-18 08:59:31 -0500439
Patrick Caulfield44f487a2007-06-06 09:21:22 -0500440 if (flags & DLM_LSFL_FS)
441 ls->ls_allocation = GFP_NOFS;
442 else
443 ls->ls_allocation = GFP_KERNEL;
444
David Teiglandfad59c12007-06-11 10:47:18 -0500445 /* ls_exflags are forced to match among nodes, and we don't
446 need to require all nodes to have TIMEWARN or FS set */
447 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
448
David Teigland68c817a2007-01-09 09:41:48 -0600449 size = dlm_config.ci_rsbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000450 ls->ls_rsbtbl_size = size;
451
452 ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL);
453 if (!ls->ls_rsbtbl)
454 goto out_lsfree;
455 for (i = 0; i < size; i++) {
456 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list);
457 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss);
458 rwlock_init(&ls->ls_rsbtbl[i].lock);
459 }
460
David Teigland68c817a2007-01-09 09:41:48 -0600461 size = dlm_config.ci_lkbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000462 ls->ls_lkbtbl_size = size;
463
464 ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL);
465 if (!ls->ls_lkbtbl)
466 goto out_rsbfree;
467 for (i = 0; i < size; i++) {
468 INIT_LIST_HEAD(&ls->ls_lkbtbl[i].list);
469 rwlock_init(&ls->ls_lkbtbl[i].lock);
470 ls->ls_lkbtbl[i].counter = 1;
471 }
472
David Teigland68c817a2007-01-09 09:41:48 -0600473 size = dlm_config.ci_dirtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000474 ls->ls_dirtbl_size = size;
475
476 ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL);
477 if (!ls->ls_dirtbl)
478 goto out_lkbfree;
479 for (i = 0; i < size; i++) {
480 INIT_LIST_HEAD(&ls->ls_dirtbl[i].list);
481 rwlock_init(&ls->ls_dirtbl[i].lock);
482 }
483
484 INIT_LIST_HEAD(&ls->ls_waiters);
David Teigland90135922006-01-20 08:47:07 +0000485 mutex_init(&ls->ls_waiters_mutex);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500486 INIT_LIST_HEAD(&ls->ls_orphans);
487 mutex_init(&ls->ls_orphans_mutex);
David Teigland3ae1acf2007-05-18 08:59:31 -0500488 INIT_LIST_HEAD(&ls->ls_timeout);
489 mutex_init(&ls->ls_timeout_mutex);
David Teiglande7fd4172006-01-18 09:30:29 +0000490
491 INIT_LIST_HEAD(&ls->ls_nodes);
492 INIT_LIST_HEAD(&ls->ls_nodes_gone);
493 ls->ls_num_nodes = 0;
494 ls->ls_low_nodeid = 0;
495 ls->ls_total_weight = 0;
496 ls->ls_node_array = NULL;
497
498 memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
499 ls->ls_stub_rsb.res_ls = ls;
500
David Teigland5de63192006-07-25 13:44:31 -0500501 ls->ls_debug_rsb_dentry = NULL;
502 ls->ls_debug_waiters_dentry = NULL;
David Teiglande7fd4172006-01-18 09:30:29 +0000503
504 init_waitqueue_head(&ls->ls_uevent_wait);
505 ls->ls_uevent_result = 0;
David Teigland8b0e7b22007-05-18 09:03:35 -0500506 init_completion(&ls->ls_members_done);
507 ls->ls_members_result = -1;
David Teiglande7fd4172006-01-18 09:30:29 +0000508
509 ls->ls_recoverd_task = NULL;
David Teigland90135922006-01-20 08:47:07 +0000510 mutex_init(&ls->ls_recoverd_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000511 spin_lock_init(&ls->ls_recover_lock);
David Teigland98f176f2006-11-27 13:19:28 -0600512 spin_lock_init(&ls->ls_rcom_spin);
513 get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
David Teiglande7fd4172006-01-18 09:30:29 +0000514 ls->ls_recover_status = 0;
515 ls->ls_recover_seq = 0;
516 ls->ls_recover_args = NULL;
517 init_rwsem(&ls->ls_in_recovery);
David Teiglandc36258b2007-09-27 15:53:38 -0500518 init_rwsem(&ls->ls_recv_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000519 INIT_LIST_HEAD(&ls->ls_requestqueue);
David Teigland90135922006-01-20 08:47:07 +0000520 mutex_init(&ls->ls_requestqueue_mutex);
David Teigland597d0ca2006-07-12 16:44:04 -0500521 mutex_init(&ls->ls_clear_proc_locks);
David Teiglande7fd4172006-01-18 09:30:29 +0000522
David Teigland68c817a2007-01-09 09:41:48 -0600523 ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000524 if (!ls->ls_recover_buf)
525 goto out_dirfree;
526
527 INIT_LIST_HEAD(&ls->ls_recover_list);
528 spin_lock_init(&ls->ls_recover_list_lock);
529 ls->ls_recover_list_count = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500530 ls->ls_local_handle = ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000531 init_waitqueue_head(&ls->ls_wait_general);
532 INIT_LIST_HEAD(&ls->ls_root_list);
533 init_rwsem(&ls->ls_root_sem);
534
535 down_write(&ls->ls_in_recovery);
536
David Teigland5f88f1e2006-08-24 14:47:20 -0500537 spin_lock(&lslist_lock);
538 list_add(&ls->ls_list, &lslist);
539 spin_unlock(&lslist_lock);
540
541 /* needs to find ls in lslist */
David Teiglande7fd4172006-01-18 09:30:29 +0000542 error = dlm_recoverd_start(ls);
543 if (error) {
544 log_error(ls, "can't start dlm_recoverd %d", error);
David Teigland79d72b52007-05-18 09:02:20 -0500545 goto out_delist;
David Teiglande7fd4172006-01-18 09:30:29 +0000546 }
547
David Teiglande7fd4172006-01-18 09:30:29 +0000548 error = kobject_setup(ls);
549 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500550 goto out_stop;
David Teiglande7fd4172006-01-18 09:30:29 +0000551
552 error = kobject_register(&ls->ls_kobj);
553 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500554 goto out_stop;
555
556 /* let kobject handle freeing of ls if there's an error */
557 do_unreg = 1;
David Teiglande7fd4172006-01-18 09:30:29 +0000558
David Teigland8b0e7b22007-05-18 09:03:35 -0500559 /* This uevent triggers dlm_controld in userspace to add us to the
560 group of nodes that are members of this lockspace (managed by the
561 cluster infrastructure.) Once it's done that, it tells us who the
562 current lockspace members are (via configfs) and then tells the
563 lockspace to start running (via sysfs) in dlm_ls_start(). */
564
David Teiglande7fd4172006-01-18 09:30:29 +0000565 error = do_uevent(ls, 1);
566 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500567 goto out_stop;
568
David Teigland8b0e7b22007-05-18 09:03:35 -0500569 wait_for_completion(&ls->ls_members_done);
570 error = ls->ls_members_result;
571 if (error)
572 goto out_members;
573
David Teigland79d72b52007-05-18 09:02:20 -0500574 dlm_create_debug_file(ls);
575
576 log_debug(ls, "join complete");
David Teiglande7fd4172006-01-18 09:30:29 +0000577
578 *lockspace = ls;
579 return 0;
580
David Teigland8b0e7b22007-05-18 09:03:35 -0500581 out_members:
582 do_uevent(ls, 0);
583 dlm_clear_members(ls);
584 kfree(ls->ls_node_array);
David Teigland79d72b52007-05-18 09:02:20 -0500585 out_stop:
David Teigland5f88f1e2006-08-24 14:47:20 -0500586 dlm_recoverd_stop(ls);
David Teigland79d72b52007-05-18 09:02:20 -0500587 out_delist:
David Teiglande7fd4172006-01-18 09:30:29 +0000588 spin_lock(&lslist_lock);
589 list_del(&ls->ls_list);
590 spin_unlock(&lslist_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000591 kfree(ls->ls_recover_buf);
592 out_dirfree:
593 kfree(ls->ls_dirtbl);
594 out_lkbfree:
595 kfree(ls->ls_lkbtbl);
596 out_rsbfree:
597 kfree(ls->ls_rsbtbl);
598 out_lsfree:
David Teigland79d72b52007-05-18 09:02:20 -0500599 if (do_unreg)
600 kobject_unregister(&ls->ls_kobj);
601 else
602 kfree(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000603 out:
604 module_put(THIS_MODULE);
605 return error;
606}
607
608int dlm_new_lockspace(char *name, int namelen, void **lockspace,
609 uint32_t flags, int lvblen)
610{
611 int error = 0;
612
David Teigland90135922006-01-20 08:47:07 +0000613 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000614 if (!ls_count)
615 error = threads_start();
616 if (error)
617 goto out;
618
619 error = new_lockspace(name, namelen, lockspace, flags, lvblen);
620 if (!error)
621 ls_count++;
David Teigland8b0e7b22007-05-18 09:03:35 -0500622 else if (!ls_count)
623 threads_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000624 out:
David Teigland90135922006-01-20 08:47:07 +0000625 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000626 return error;
627}
628
629/* Return 1 if the lockspace still has active remote locks,
630 * 2 if the lockspace still has active local locks.
631 */
632static int lockspace_busy(struct dlm_ls *ls)
633{
634 int i, lkb_found = 0;
635 struct dlm_lkb *lkb;
636
637 /* NOTE: We check the lockidtbl here rather than the resource table.
638 This is because there may be LKBs queued as ASTs that have been
639 unlinked from their RSBs and are pending deletion once the AST has
640 been delivered */
641
642 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
643 read_lock(&ls->ls_lkbtbl[i].lock);
644 if (!list_empty(&ls->ls_lkbtbl[i].list)) {
645 lkb_found = 1;
646 list_for_each_entry(lkb, &ls->ls_lkbtbl[i].list,
647 lkb_idtbl_list) {
648 if (!lkb->lkb_nodeid) {
649 read_unlock(&ls->ls_lkbtbl[i].lock);
650 return 2;
651 }
652 }
653 }
654 read_unlock(&ls->ls_lkbtbl[i].lock);
655 }
656 return lkb_found;
657}
658
659static int release_lockspace(struct dlm_ls *ls, int force)
660{
661 struct dlm_lkb *lkb;
662 struct dlm_rsb *rsb;
663 struct list_head *head;
664 int i;
665 int busy = lockspace_busy(ls);
666
667 if (busy > force)
668 return -EBUSY;
669
670 if (force < 3)
671 do_uevent(ls, 0);
672
673 dlm_recoverd_stop(ls);
674
675 remove_lockspace(ls);
676
677 dlm_delete_debug_file(ls);
678
679 dlm_astd_suspend();
680
681 kfree(ls->ls_recover_buf);
682
683 /*
684 * Free direntry structs.
685 */
686
687 dlm_dir_clear(ls);
688 kfree(ls->ls_dirtbl);
689
690 /*
691 * Free all lkb's on lkbtbl[] lists.
692 */
693
694 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
695 head = &ls->ls_lkbtbl[i].list;
696 while (!list_empty(head)) {
697 lkb = list_entry(head->next, struct dlm_lkb,
698 lkb_idtbl_list);
699
700 list_del(&lkb->lkb_idtbl_list);
701
702 dlm_del_ast(lkb);
703
704 if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
705 free_lvb(lkb->lkb_lvbptr);
706
707 free_lkb(lkb);
708 }
709 }
710 dlm_astd_resume();
711
712 kfree(ls->ls_lkbtbl);
713
714 /*
715 * Free all rsb's on rsbtbl[] lists
716 */
717
718 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
719 head = &ls->ls_rsbtbl[i].list;
720 while (!list_empty(head)) {
721 rsb = list_entry(head->next, struct dlm_rsb,
722 res_hashchain);
723
724 list_del(&rsb->res_hashchain);
725 free_rsb(rsb);
726 }
727
728 head = &ls->ls_rsbtbl[i].toss;
729 while (!list_empty(head)) {
730 rsb = list_entry(head->next, struct dlm_rsb,
731 res_hashchain);
732 list_del(&rsb->res_hashchain);
733 free_rsb(rsb);
734 }
735 }
736
737 kfree(ls->ls_rsbtbl);
738
739 /*
740 * Free structures on any other lists
741 */
742
David Teigland2896ee32006-11-27 11:31:22 -0600743 dlm_purge_requestqueue(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000744 kfree(ls->ls_recover_args);
745 dlm_clear_free_entries(ls);
746 dlm_clear_members(ls);
747 dlm_clear_members_gone(ls);
748 kfree(ls->ls_node_array);
749 kobject_unregister(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500750 /* The ls structure will be freed when the kobject is done with */
David Teiglande7fd4172006-01-18 09:30:29 +0000751
David Teigland90135922006-01-20 08:47:07 +0000752 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000753 ls_count--;
754 if (!ls_count)
755 threads_stop();
David Teigland90135922006-01-20 08:47:07 +0000756 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000757
758 module_put(THIS_MODULE);
759 return 0;
760}
761
762/*
763 * Called when a system has released all its locks and is not going to use the
764 * lockspace any longer. We free everything we're managing for this lockspace.
765 * Remaining nodes will go through the recovery process as if we'd died. The
766 * lockspace must continue to function as usual, participating in recoveries,
767 * until this returns.
768 *
769 * Force has 4 possible values:
770 * 0 - don't destroy locksapce if it has any LKBs
771 * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
772 * 2 - destroy lockspace regardless of LKBs
773 * 3 - destroy lockspace as part of a forced shutdown
774 */
775
776int dlm_release_lockspace(void *lockspace, int force)
777{
778 struct dlm_ls *ls;
779
780 ls = dlm_find_lockspace_local(lockspace);
781 if (!ls)
782 return -EINVAL;
783 dlm_put_lockspace(ls);
784 return release_lockspace(ls, force);
785}
786