blob: 499e16759e96fea13329dc05d5408194fa96e4e9 [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
David Teiglande7fd4172006-01-18 09:30:29 +000027static int ls_count;
David Teigland90135922006-01-20 08:47:07 +000028static struct mutex ls_lock;
David Teiglande7fd4172006-01-18 09:30:29 +000029static struct list_head lslist;
30static spinlock_t lslist_lock;
31static struct task_struct * scand_task;
32
33
34static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
35{
36 ssize_t ret = len;
37 int n = simple_strtol(buf, NULL, 0);
38
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000039 ls = dlm_find_lockspace_local(ls->ls_local_handle);
40 if (!ls)
41 return -EINVAL;
42
David Teiglande7fd4172006-01-18 09:30:29 +000043 switch (n) {
44 case 0:
45 dlm_ls_stop(ls);
46 break;
47 case 1:
48 dlm_ls_start(ls);
49 break;
50 default:
51 ret = -EINVAL;
52 }
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000053 dlm_put_lockspace(ls);
David Teiglande7fd4172006-01-18 09:30:29 +000054 return ret;
55}
56
57static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
58{
59 ls->ls_uevent_result = simple_strtol(buf, NULL, 0);
60 set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
61 wake_up(&ls->ls_uevent_wait);
62 return len;
63}
64
65static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
66{
David Teiglanda1d144c2006-09-06 17:01:40 -050067 return snprintf(buf, PAGE_SIZE, "%u\n", ls->ls_global_id);
David Teiglande7fd4172006-01-18 09:30:29 +000068}
69
70static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
71{
72 ls->ls_global_id = simple_strtoul(buf, NULL, 0);
73 return len;
74}
75
David Teiglandc56b39c2006-04-28 10:51:53 -040076static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
77{
78 uint32_t status = dlm_recover_status(ls);
David Teiglanda1d144c2006-09-06 17:01:40 -050079 return snprintf(buf, PAGE_SIZE, "%x\n", status);
David Teiglandc56b39c2006-04-28 10:51:53 -040080}
81
David Teiglandfaa0f262006-08-08 17:08:42 -050082static ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf)
83{
David Teiglanda1d144c2006-09-06 17:01:40 -050084 return snprintf(buf, PAGE_SIZE, "%d\n", ls->ls_recover_nodeid);
David Teiglandfaa0f262006-08-08 17:08:42 -050085}
86
David Teiglande7fd4172006-01-18 09:30:29 +000087struct dlm_attr {
88 struct attribute attr;
89 ssize_t (*show)(struct dlm_ls *, char *);
90 ssize_t (*store)(struct dlm_ls *, const char *, size_t);
91};
92
93static struct dlm_attr dlm_attr_control = {
94 .attr = {.name = "control", .mode = S_IWUSR},
95 .store = dlm_control_store
96};
97
98static struct dlm_attr dlm_attr_event = {
99 .attr = {.name = "event_done", .mode = S_IWUSR},
100 .store = dlm_event_store
101};
102
103static struct dlm_attr dlm_attr_id = {
104 .attr = {.name = "id", .mode = S_IRUGO | S_IWUSR},
105 .show = dlm_id_show,
106 .store = dlm_id_store
107};
108
David Teiglandc56b39c2006-04-28 10:51:53 -0400109static struct dlm_attr dlm_attr_recover_status = {
110 .attr = {.name = "recover_status", .mode = S_IRUGO},
111 .show = dlm_recover_status_show
112};
113
David Teiglandfaa0f262006-08-08 17:08:42 -0500114static struct dlm_attr dlm_attr_recover_nodeid = {
115 .attr = {.name = "recover_nodeid", .mode = S_IRUGO},
116 .show = dlm_recover_nodeid_show
117};
118
David Teiglande7fd4172006-01-18 09:30:29 +0000119static struct attribute *dlm_attrs[] = {
120 &dlm_attr_control.attr,
121 &dlm_attr_event.attr,
122 &dlm_attr_id.attr,
David Teiglandc56b39c2006-04-28 10:51:53 -0400123 &dlm_attr_recover_status.attr,
David Teiglandfaa0f262006-08-08 17:08:42 -0500124 &dlm_attr_recover_nodeid.attr,
David Teiglande7fd4172006-01-18 09:30:29 +0000125 NULL,
126};
127
128static ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr,
129 char *buf)
130{
131 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
132 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
133 return a->show ? a->show(ls, buf) : 0;
134}
135
136static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
137 const char *buf, size_t len)
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->store ? a->store(ls, buf, len) : len;
142}
143
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000144static void lockspace_kobj_release(struct kobject *k)
145{
146 struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj);
147 kfree(ls);
148}
149
David Teiglande7fd4172006-01-18 09:30:29 +0000150static struct sysfs_ops dlm_attr_ops = {
151 .show = dlm_attr_show,
152 .store = dlm_attr_store,
153};
154
155static struct kobj_type dlm_ktype = {
156 .default_attrs = dlm_attrs,
157 .sysfs_ops = &dlm_attr_ops,
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000158 .release = lockspace_kobj_release,
David Teiglande7fd4172006-01-18 09:30:29 +0000159};
160
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100161static struct kset *dlm_kset;
David Teiglande7fd4172006-01-18 09:30:29 +0000162
David Teiglande7fd4172006-01-18 09:30:29 +0000163static int do_uevent(struct dlm_ls *ls, int in)
164{
165 int error;
166
167 if (in)
168 kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
169 else
170 kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
171
David Teigland8b0e7b22007-05-18 09:03:35 -0500172 log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
173
174 /* dlm_controld will see the uevent, do the necessary group management
175 and then write to sysfs to wake us */
176
David Teiglande7fd4172006-01-18 09:30:29 +0000177 error = wait_event_interruptible(ls->ls_uevent_wait,
178 test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
David Teigland8b0e7b22007-05-18 09:03:35 -0500179
180 log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
181
David Teiglande7fd4172006-01-18 09:30:29 +0000182 if (error)
183 goto out;
184
185 error = ls->ls_uevent_result;
186 out:
David Teigland8b0e7b22007-05-18 09:03:35 -0500187 if (error)
188 log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
189 error, ls->ls_uevent_result);
David Teiglande7fd4172006-01-18 09:30:29 +0000190 return error;
191}
192
193
Denis Cheng30727172008-02-02 01:53:46 +0800194int __init dlm_lockspace_init(void)
David Teiglande7fd4172006-01-18 09:30:29 +0000195{
David Teiglande7fd4172006-01-18 09:30:29 +0000196 ls_count = 0;
David Teigland90135922006-01-20 08:47:07 +0000197 mutex_init(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000198 INIT_LIST_HEAD(&lslist);
199 spin_lock_init(&lslist_lock);
200
Greg Kroah-Hartman0ff21e42007-11-06 10:36:58 -0800201 dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100202 if (!dlm_kset) {
Harvey Harrison8e24eea2008-04-30 00:55:09 -0700203 printk(KERN_WARNING "%s: can not create kset\n", __func__);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100204 return -ENOMEM;
205 }
206 return 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000207}
208
209void dlm_lockspace_exit(void)
210{
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100211 kset_unregister(dlm_kset);
David Teiglande7fd4172006-01-18 09:30:29 +0000212}
213
214static int dlm_scand(void *data)
215{
216 struct dlm_ls *ls;
217
218 while (!kthread_should_stop()) {
David Teigland85e86ed2007-05-18 08:58:15 -0500219 list_for_each_entry(ls, &lslist, ls_list) {
220 if (dlm_lock_recovery_try(ls)) {
221 dlm_scan_rsbs(ls);
David Teigland3ae1acf2007-05-18 08:59:31 -0500222 dlm_scan_timeout(ls);
David Teigland85e86ed2007-05-18 08:58:15 -0500223 dlm_unlock_recovery(ls);
224 }
225 }
David Teigland68c817a2007-01-09 09:41:48 -0600226 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
David Teiglande7fd4172006-01-18 09:30:29 +0000227 }
228 return 0;
229}
230
231static int dlm_scand_start(void)
232{
233 struct task_struct *p;
234 int error = 0;
235
236 p = kthread_run(dlm_scand, NULL, "dlm_scand");
237 if (IS_ERR(p))
238 error = PTR_ERR(p);
239 else
240 scand_task = p;
241 return error;
242}
243
244static void dlm_scand_stop(void)
245{
246 kthread_stop(scand_task);
247}
248
249static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
250{
251 struct dlm_ls *ls;
252
253 spin_lock(&lslist_lock);
254
255 list_for_each_entry(ls, &lslist, ls_list) {
256 if (ls->ls_namelen == namelen &&
257 memcmp(ls->ls_name, name, namelen) == 0)
258 goto out;
259 }
260 ls = NULL;
261 out:
262 spin_unlock(&lslist_lock);
263 return ls;
264}
265
266struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
267{
268 struct dlm_ls *ls;
269
270 spin_lock(&lslist_lock);
271
272 list_for_each_entry(ls, &lslist, ls_list) {
273 if (ls->ls_global_id == id) {
274 ls->ls_count++;
275 goto out;
276 }
277 }
278 ls = NULL;
279 out:
280 spin_unlock(&lslist_lock);
281 return ls;
282}
283
David Teigland597d0ca2006-07-12 16:44:04 -0500284struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000285{
David Teigland597d0ca2006-07-12 16:44:04 -0500286 struct dlm_ls *ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000287
288 spin_lock(&lslist_lock);
David Teigland597d0ca2006-07-12 16:44:04 -0500289 list_for_each_entry(ls, &lslist, ls_list) {
290 if (ls->ls_local_handle == lockspace) {
291 ls->ls_count++;
292 goto out;
293 }
294 }
295 ls = NULL;
296 out:
297 spin_unlock(&lslist_lock);
298 return ls;
299}
300
301struct dlm_ls *dlm_find_lockspace_device(int minor)
302{
303 struct dlm_ls *ls;
304
305 spin_lock(&lslist_lock);
306 list_for_each_entry(ls, &lslist, ls_list) {
307 if (ls->ls_device.minor == minor) {
308 ls->ls_count++;
309 goto out;
310 }
311 }
312 ls = NULL;
313 out:
David Teiglande7fd4172006-01-18 09:30:29 +0000314 spin_unlock(&lslist_lock);
315 return ls;
316}
317
318void dlm_put_lockspace(struct dlm_ls *ls)
319{
320 spin_lock(&lslist_lock);
321 ls->ls_count--;
322 spin_unlock(&lslist_lock);
323}
324
325static void remove_lockspace(struct dlm_ls *ls)
326{
327 for (;;) {
328 spin_lock(&lslist_lock);
329 if (ls->ls_count == 0) {
330 list_del(&ls->ls_list);
331 spin_unlock(&lslist_lock);
332 return;
333 }
334 spin_unlock(&lslist_lock);
335 ssleep(1);
336 }
337}
338
339static int threads_start(void)
340{
341 int error;
342
343 /* Thread which process lock requests for all lockspace's */
344 error = dlm_astd_start();
345 if (error) {
346 log_print("cannot start dlm_astd thread %d", error);
347 goto fail;
348 }
349
350 error = dlm_scand_start();
351 if (error) {
352 log_print("cannot start dlm_scand thread %d", error);
353 goto astd_fail;
354 }
355
356 /* Thread for sending/receiving messages for all lockspace's */
357 error = dlm_lowcomms_start();
358 if (error) {
359 log_print("cannot start dlm lowcomms %d", error);
360 goto scand_fail;
361 }
362
363 return 0;
364
365 scand_fail:
366 dlm_scand_stop();
367 astd_fail:
368 dlm_astd_stop();
369 fail:
370 return error;
371}
372
373static void threads_stop(void)
374{
375 dlm_scand_stop();
376 dlm_lowcomms_stop();
377 dlm_astd_stop();
378}
379
380static int new_lockspace(char *name, int namelen, void **lockspace,
381 uint32_t flags, int lvblen)
382{
383 struct dlm_ls *ls;
384 int i, size, error = -ENOMEM;
David Teigland79d72b52007-05-18 09:02:20 -0500385 int do_unreg = 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000386
387 if (namelen > DLM_LOCKSPACE_LEN)
388 return -EINVAL;
389
390 if (!lvblen || (lvblen % 8))
391 return -EINVAL;
392
393 if (!try_module_get(THIS_MODULE))
394 return -EINVAL;
395
396 ls = dlm_find_lockspace_name(name, namelen);
397 if (ls) {
398 *lockspace = ls;
399 module_put(THIS_MODULE);
400 return -EEXIST;
401 }
402
David Teigland90135922006-01-20 08:47:07 +0000403 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000404 if (!ls)
405 goto out;
David Teiglande7fd4172006-01-18 09:30:29 +0000406 memcpy(ls->ls_name, name, namelen);
407 ls->ls_namelen = namelen;
David Teiglande7fd4172006-01-18 09:30:29 +0000408 ls->ls_lvblen = lvblen;
409 ls->ls_count = 0;
410 ls->ls_flags = 0;
411
David Teigland3ae1acf2007-05-18 08:59:31 -0500412 if (flags & DLM_LSFL_TIMEWARN)
413 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
David Teigland3ae1acf2007-05-18 08:59:31 -0500414
Patrick Caulfield44f487a2007-06-06 09:21:22 -0500415 if (flags & DLM_LSFL_FS)
416 ls->ls_allocation = GFP_NOFS;
417 else
418 ls->ls_allocation = GFP_KERNEL;
419
David Teiglandfad59c12007-06-11 10:47:18 -0500420 /* ls_exflags are forced to match among nodes, and we don't
421 need to require all nodes to have TIMEWARN or FS set */
422 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
423
David Teigland68c817a2007-01-09 09:41:48 -0600424 size = dlm_config.ci_rsbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000425 ls->ls_rsbtbl_size = size;
426
427 ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL);
428 if (!ls->ls_rsbtbl)
429 goto out_lsfree;
430 for (i = 0; i < size; i++) {
431 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list);
432 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss);
433 rwlock_init(&ls->ls_rsbtbl[i].lock);
434 }
435
David Teigland68c817a2007-01-09 09:41:48 -0600436 size = dlm_config.ci_lkbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000437 ls->ls_lkbtbl_size = size;
438
439 ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL);
440 if (!ls->ls_lkbtbl)
441 goto out_rsbfree;
442 for (i = 0; i < size; i++) {
443 INIT_LIST_HEAD(&ls->ls_lkbtbl[i].list);
444 rwlock_init(&ls->ls_lkbtbl[i].lock);
445 ls->ls_lkbtbl[i].counter = 1;
446 }
447
David Teigland68c817a2007-01-09 09:41:48 -0600448 size = dlm_config.ci_dirtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000449 ls->ls_dirtbl_size = size;
450
451 ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL);
452 if (!ls->ls_dirtbl)
453 goto out_lkbfree;
454 for (i = 0; i < size; i++) {
455 INIT_LIST_HEAD(&ls->ls_dirtbl[i].list);
456 rwlock_init(&ls->ls_dirtbl[i].lock);
457 }
458
459 INIT_LIST_HEAD(&ls->ls_waiters);
David Teigland90135922006-01-20 08:47:07 +0000460 mutex_init(&ls->ls_waiters_mutex);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500461 INIT_LIST_HEAD(&ls->ls_orphans);
462 mutex_init(&ls->ls_orphans_mutex);
David Teigland3ae1acf2007-05-18 08:59:31 -0500463 INIT_LIST_HEAD(&ls->ls_timeout);
464 mutex_init(&ls->ls_timeout_mutex);
David Teiglande7fd4172006-01-18 09:30:29 +0000465
466 INIT_LIST_HEAD(&ls->ls_nodes);
467 INIT_LIST_HEAD(&ls->ls_nodes_gone);
468 ls->ls_num_nodes = 0;
469 ls->ls_low_nodeid = 0;
470 ls->ls_total_weight = 0;
471 ls->ls_node_array = NULL;
472
473 memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
474 ls->ls_stub_rsb.res_ls = ls;
475
David Teigland5de63192006-07-25 13:44:31 -0500476 ls->ls_debug_rsb_dentry = NULL;
477 ls->ls_debug_waiters_dentry = NULL;
David Teiglande7fd4172006-01-18 09:30:29 +0000478
479 init_waitqueue_head(&ls->ls_uevent_wait);
480 ls->ls_uevent_result = 0;
David Teigland8b0e7b22007-05-18 09:03:35 -0500481 init_completion(&ls->ls_members_done);
482 ls->ls_members_result = -1;
David Teiglande7fd4172006-01-18 09:30:29 +0000483
484 ls->ls_recoverd_task = NULL;
David Teigland90135922006-01-20 08:47:07 +0000485 mutex_init(&ls->ls_recoverd_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000486 spin_lock_init(&ls->ls_recover_lock);
David Teigland98f176f2006-11-27 13:19:28 -0600487 spin_lock_init(&ls->ls_rcom_spin);
488 get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
David Teiglande7fd4172006-01-18 09:30:29 +0000489 ls->ls_recover_status = 0;
490 ls->ls_recover_seq = 0;
491 ls->ls_recover_args = NULL;
492 init_rwsem(&ls->ls_in_recovery);
David Teiglandc36258b2007-09-27 15:53:38 -0500493 init_rwsem(&ls->ls_recv_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000494 INIT_LIST_HEAD(&ls->ls_requestqueue);
David Teigland90135922006-01-20 08:47:07 +0000495 mutex_init(&ls->ls_requestqueue_mutex);
David Teigland597d0ca2006-07-12 16:44:04 -0500496 mutex_init(&ls->ls_clear_proc_locks);
David Teiglande7fd4172006-01-18 09:30:29 +0000497
David Teigland68c817a2007-01-09 09:41:48 -0600498 ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000499 if (!ls->ls_recover_buf)
500 goto out_dirfree;
501
502 INIT_LIST_HEAD(&ls->ls_recover_list);
503 spin_lock_init(&ls->ls_recover_list_lock);
504 ls->ls_recover_list_count = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500505 ls->ls_local_handle = ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000506 init_waitqueue_head(&ls->ls_wait_general);
507 INIT_LIST_HEAD(&ls->ls_root_list);
508 init_rwsem(&ls->ls_root_sem);
509
510 down_write(&ls->ls_in_recovery);
511
David Teigland5f88f1e2006-08-24 14:47:20 -0500512 spin_lock(&lslist_lock);
513 list_add(&ls->ls_list, &lslist);
514 spin_unlock(&lslist_lock);
515
516 /* needs to find ls in lslist */
David Teiglande7fd4172006-01-18 09:30:29 +0000517 error = dlm_recoverd_start(ls);
518 if (error) {
519 log_error(ls, "can't start dlm_recoverd %d", error);
David Teigland79d72b52007-05-18 09:02:20 -0500520 goto out_delist;
David Teiglande7fd4172006-01-18 09:30:29 +0000521 }
522
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400523 ls->ls_kobj.kset = dlm_kset;
524 error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
525 "%s", ls->ls_name);
David Teiglande7fd4172006-01-18 09:30:29 +0000526 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500527 goto out_stop;
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400528 kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
David Teigland79d72b52007-05-18 09:02:20 -0500529
530 /* let kobject handle freeing of ls if there's an error */
531 do_unreg = 1;
David Teiglande7fd4172006-01-18 09:30:29 +0000532
David Teigland8b0e7b22007-05-18 09:03:35 -0500533 /* This uevent triggers dlm_controld in userspace to add us to the
534 group of nodes that are members of this lockspace (managed by the
535 cluster infrastructure.) Once it's done that, it tells us who the
536 current lockspace members are (via configfs) and then tells the
537 lockspace to start running (via sysfs) in dlm_ls_start(). */
538
David Teiglande7fd4172006-01-18 09:30:29 +0000539 error = do_uevent(ls, 1);
540 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500541 goto out_stop;
542
David Teigland8b0e7b22007-05-18 09:03:35 -0500543 wait_for_completion(&ls->ls_members_done);
544 error = ls->ls_members_result;
545 if (error)
546 goto out_members;
547
David Teigland79d72b52007-05-18 09:02:20 -0500548 dlm_create_debug_file(ls);
549
550 log_debug(ls, "join complete");
David Teiglande7fd4172006-01-18 09:30:29 +0000551
552 *lockspace = ls;
553 return 0;
554
David Teigland8b0e7b22007-05-18 09:03:35 -0500555 out_members:
556 do_uevent(ls, 0);
557 dlm_clear_members(ls);
558 kfree(ls->ls_node_array);
David Teigland79d72b52007-05-18 09:02:20 -0500559 out_stop:
David Teigland5f88f1e2006-08-24 14:47:20 -0500560 dlm_recoverd_stop(ls);
David Teigland79d72b52007-05-18 09:02:20 -0500561 out_delist:
David Teiglande7fd4172006-01-18 09:30:29 +0000562 spin_lock(&lslist_lock);
563 list_del(&ls->ls_list);
564 spin_unlock(&lslist_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000565 kfree(ls->ls_recover_buf);
566 out_dirfree:
567 kfree(ls->ls_dirtbl);
568 out_lkbfree:
569 kfree(ls->ls_lkbtbl);
570 out_rsbfree:
571 kfree(ls->ls_rsbtbl);
572 out_lsfree:
David Teigland79d72b52007-05-18 09:02:20 -0500573 if (do_unreg)
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800574 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500575 else
576 kfree(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000577 out:
578 module_put(THIS_MODULE);
579 return error;
580}
581
582int dlm_new_lockspace(char *name, int namelen, void **lockspace,
583 uint32_t flags, int lvblen)
584{
585 int error = 0;
586
David Teigland90135922006-01-20 08:47:07 +0000587 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000588 if (!ls_count)
589 error = threads_start();
590 if (error)
591 goto out;
592
593 error = new_lockspace(name, namelen, lockspace, flags, lvblen);
594 if (!error)
595 ls_count++;
David Teigland8b0e7b22007-05-18 09:03:35 -0500596 else if (!ls_count)
597 threads_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000598 out:
David Teigland90135922006-01-20 08:47:07 +0000599 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000600 return error;
601}
602
603/* Return 1 if the lockspace still has active remote locks,
604 * 2 if the lockspace still has active local locks.
605 */
606static int lockspace_busy(struct dlm_ls *ls)
607{
608 int i, lkb_found = 0;
609 struct dlm_lkb *lkb;
610
611 /* NOTE: We check the lockidtbl here rather than the resource table.
612 This is because there may be LKBs queued as ASTs that have been
613 unlinked from their RSBs and are pending deletion once the AST has
614 been delivered */
615
616 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
617 read_lock(&ls->ls_lkbtbl[i].lock);
618 if (!list_empty(&ls->ls_lkbtbl[i].list)) {
619 lkb_found = 1;
620 list_for_each_entry(lkb, &ls->ls_lkbtbl[i].list,
621 lkb_idtbl_list) {
622 if (!lkb->lkb_nodeid) {
623 read_unlock(&ls->ls_lkbtbl[i].lock);
624 return 2;
625 }
626 }
627 }
628 read_unlock(&ls->ls_lkbtbl[i].lock);
629 }
630 return lkb_found;
631}
632
633static int release_lockspace(struct dlm_ls *ls, int force)
634{
635 struct dlm_lkb *lkb;
636 struct dlm_rsb *rsb;
637 struct list_head *head;
638 int i;
639 int busy = lockspace_busy(ls);
640
641 if (busy > force)
642 return -EBUSY;
643
644 if (force < 3)
645 do_uevent(ls, 0);
646
647 dlm_recoverd_stop(ls);
648
649 remove_lockspace(ls);
650
651 dlm_delete_debug_file(ls);
652
653 dlm_astd_suspend();
654
655 kfree(ls->ls_recover_buf);
656
657 /*
658 * Free direntry structs.
659 */
660
661 dlm_dir_clear(ls);
662 kfree(ls->ls_dirtbl);
663
664 /*
665 * Free all lkb's on lkbtbl[] lists.
666 */
667
668 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
669 head = &ls->ls_lkbtbl[i].list;
670 while (!list_empty(head)) {
671 lkb = list_entry(head->next, struct dlm_lkb,
672 lkb_idtbl_list);
673
674 list_del(&lkb->lkb_idtbl_list);
675
676 dlm_del_ast(lkb);
677
678 if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
David Teigland52bda2b2007-11-07 09:06:49 -0600679 dlm_free_lvb(lkb->lkb_lvbptr);
David Teiglande7fd4172006-01-18 09:30:29 +0000680
David Teigland52bda2b2007-11-07 09:06:49 -0600681 dlm_free_lkb(lkb);
David Teiglande7fd4172006-01-18 09:30:29 +0000682 }
683 }
684 dlm_astd_resume();
685
686 kfree(ls->ls_lkbtbl);
687
688 /*
689 * Free all rsb's on rsbtbl[] lists
690 */
691
692 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
693 head = &ls->ls_rsbtbl[i].list;
694 while (!list_empty(head)) {
695 rsb = list_entry(head->next, struct dlm_rsb,
696 res_hashchain);
697
698 list_del(&rsb->res_hashchain);
David Teigland52bda2b2007-11-07 09:06:49 -0600699 dlm_free_rsb(rsb);
David Teiglande7fd4172006-01-18 09:30:29 +0000700 }
701
702 head = &ls->ls_rsbtbl[i].toss;
703 while (!list_empty(head)) {
704 rsb = list_entry(head->next, struct dlm_rsb,
705 res_hashchain);
706 list_del(&rsb->res_hashchain);
David Teigland52bda2b2007-11-07 09:06:49 -0600707 dlm_free_rsb(rsb);
David Teiglande7fd4172006-01-18 09:30:29 +0000708 }
709 }
710
711 kfree(ls->ls_rsbtbl);
712
713 /*
714 * Free structures on any other lists
715 */
716
David Teigland2896ee32006-11-27 11:31:22 -0600717 dlm_purge_requestqueue(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000718 kfree(ls->ls_recover_args);
719 dlm_clear_free_entries(ls);
720 dlm_clear_members(ls);
721 dlm_clear_members_gone(ls);
722 kfree(ls->ls_node_array);
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800723 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500724 /* The ls structure will be freed when the kobject is done with */
David Teiglande7fd4172006-01-18 09:30:29 +0000725
David Teigland90135922006-01-20 08:47:07 +0000726 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000727 ls_count--;
728 if (!ls_count)
729 threads_stop();
David Teigland90135922006-01-20 08:47:07 +0000730 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000731
732 module_put(THIS_MODULE);
733 return 0;
734}
735
736/*
737 * Called when a system has released all its locks and is not going to use the
738 * lockspace any longer. We free everything we're managing for this lockspace.
739 * Remaining nodes will go through the recovery process as if we'd died. The
740 * lockspace must continue to function as usual, participating in recoveries,
741 * until this returns.
742 *
743 * Force has 4 possible values:
744 * 0 - don't destroy locksapce if it has any LKBs
745 * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
746 * 2 - destroy lockspace regardless of LKBs
747 * 3 - destroy lockspace as part of a forced shutdown
748 */
749
750int dlm_release_lockspace(void *lockspace, int force)
751{
752 struct dlm_ls *ls;
753
754 ls = dlm_find_lockspace_local(lockspace);
755 if (!ls)
756 return -EINVAL;
757 dlm_put_lockspace(ls);
758 return release_lockspace(ls, force);
759}
760