blob: a3a50e67e4dd4855e993612f55d541916faae06d [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
169static struct kset dlm_kset = {
David Teiglande7fd4172006-01-18 09:30:29 +0000170 .kobj = {.name = "dlm",},
171 .ktype = &dlm_ktype,
172};
173
174static int kobject_setup(struct dlm_ls *ls)
175{
176 char lsname[DLM_LOCKSPACE_LEN];
177 int error;
178
179 memset(lsname, 0, DLM_LOCKSPACE_LEN);
180 snprintf(lsname, DLM_LOCKSPACE_LEN, "%s", ls->ls_name);
181
182 error = kobject_set_name(&ls->ls_kobj, "%s", lsname);
183 if (error)
184 return error;
185
186 ls->ls_kobj.kset = &dlm_kset;
187 ls->ls_kobj.ktype = &dlm_ktype;
188 return 0;
189}
190
191static int do_uevent(struct dlm_ls *ls, int in)
192{
193 int error;
194
195 if (in)
196 kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
197 else
198 kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
199
200 error = wait_event_interruptible(ls->ls_uevent_wait,
201 test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
202 if (error)
203 goto out;
204
205 error = ls->ls_uevent_result;
206 out:
207 return error;
208}
209
210
211int dlm_lockspace_init(void)
212{
213 int error;
214
215 ls_count = 0;
David Teigland90135922006-01-20 08:47:07 +0000216 mutex_init(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000217 INIT_LIST_HEAD(&lslist);
218 spin_lock_init(&lslist_lock);
219
Greg Kroah-Hartman823bccf2007-04-13 13:15:19 -0700220 kobj_set_kset_s(&dlm_kset, kernel_subsys);
David Teiglande7fd4172006-01-18 09:30:29 +0000221 error = kset_register(&dlm_kset);
222 if (error)
223 printk("dlm_lockspace_init: cannot register kset %d\n", error);
224 return error;
225}
226
227void dlm_lockspace_exit(void)
228{
229 kset_unregister(&dlm_kset);
230}
231
232static int dlm_scand(void *data)
233{
234 struct dlm_ls *ls;
235
236 while (!kthread_should_stop()) {
David Teigland85e86ed2007-05-18 08:58:15 -0500237 list_for_each_entry(ls, &lslist, ls_list) {
238 if (dlm_lock_recovery_try(ls)) {
239 dlm_scan_rsbs(ls);
David Teigland3ae1acf2007-05-18 08:59:31 -0500240 dlm_scan_timeout(ls);
David Teigland85e86ed2007-05-18 08:58:15 -0500241 dlm_unlock_recovery(ls);
242 }
243 }
David Teigland68c817a2007-01-09 09:41:48 -0600244 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
David Teiglande7fd4172006-01-18 09:30:29 +0000245 }
246 return 0;
247}
248
249static int dlm_scand_start(void)
250{
251 struct task_struct *p;
252 int error = 0;
253
254 p = kthread_run(dlm_scand, NULL, "dlm_scand");
255 if (IS_ERR(p))
256 error = PTR_ERR(p);
257 else
258 scand_task = p;
259 return error;
260}
261
262static void dlm_scand_stop(void)
263{
264 kthread_stop(scand_task);
265}
266
267static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen)
268{
269 struct dlm_ls *ls;
270
271 spin_lock(&lslist_lock);
272
273 list_for_each_entry(ls, &lslist, ls_list) {
274 if (ls->ls_namelen == namelen &&
275 memcmp(ls->ls_name, name, namelen) == 0)
276 goto out;
277 }
278 ls = NULL;
279 out:
280 spin_unlock(&lslist_lock);
281 return ls;
282}
283
284struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
285{
286 struct dlm_ls *ls;
287
288 spin_lock(&lslist_lock);
289
290 list_for_each_entry(ls, &lslist, ls_list) {
291 if (ls->ls_global_id == id) {
292 ls->ls_count++;
293 goto out;
294 }
295 }
296 ls = NULL;
297 out:
298 spin_unlock(&lslist_lock);
299 return ls;
300}
301
David Teigland597d0ca2006-07-12 16:44:04 -0500302struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000303{
David Teigland597d0ca2006-07-12 16:44:04 -0500304 struct dlm_ls *ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000305
306 spin_lock(&lslist_lock);
David Teigland597d0ca2006-07-12 16:44:04 -0500307 list_for_each_entry(ls, &lslist, ls_list) {
308 if (ls->ls_local_handle == lockspace) {
309 ls->ls_count++;
310 goto out;
311 }
312 }
313 ls = NULL;
314 out:
315 spin_unlock(&lslist_lock);
316 return ls;
317}
318
319struct dlm_ls *dlm_find_lockspace_device(int minor)
320{
321 struct dlm_ls *ls;
322
323 spin_lock(&lslist_lock);
324 list_for_each_entry(ls, &lslist, ls_list) {
325 if (ls->ls_device.minor == minor) {
326 ls->ls_count++;
327 goto out;
328 }
329 }
330 ls = NULL;
331 out:
David Teiglande7fd4172006-01-18 09:30:29 +0000332 spin_unlock(&lslist_lock);
333 return ls;
334}
335
336void dlm_put_lockspace(struct dlm_ls *ls)
337{
338 spin_lock(&lslist_lock);
339 ls->ls_count--;
340 spin_unlock(&lslist_lock);
341}
342
343static void remove_lockspace(struct dlm_ls *ls)
344{
345 for (;;) {
346 spin_lock(&lslist_lock);
347 if (ls->ls_count == 0) {
348 list_del(&ls->ls_list);
349 spin_unlock(&lslist_lock);
350 return;
351 }
352 spin_unlock(&lslist_lock);
353 ssleep(1);
354 }
355}
356
357static int threads_start(void)
358{
359 int error;
360
361 /* Thread which process lock requests for all lockspace's */
362 error = dlm_astd_start();
363 if (error) {
364 log_print("cannot start dlm_astd thread %d", error);
365 goto fail;
366 }
367
368 error = dlm_scand_start();
369 if (error) {
370 log_print("cannot start dlm_scand thread %d", error);
371 goto astd_fail;
372 }
373
374 /* Thread for sending/receiving messages for all lockspace's */
375 error = dlm_lowcomms_start();
376 if (error) {
377 log_print("cannot start dlm lowcomms %d", error);
378 goto scand_fail;
379 }
380
381 return 0;
382
383 scand_fail:
384 dlm_scand_stop();
385 astd_fail:
386 dlm_astd_stop();
387 fail:
388 return error;
389}
390
391static void threads_stop(void)
392{
393 dlm_scand_stop();
394 dlm_lowcomms_stop();
395 dlm_astd_stop();
396}
397
398static int new_lockspace(char *name, int namelen, void **lockspace,
399 uint32_t flags, int lvblen)
400{
401 struct dlm_ls *ls;
402 int i, size, error = -ENOMEM;
David Teigland79d72b52007-05-18 09:02:20 -0500403 int do_unreg = 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000404
405 if (namelen > DLM_LOCKSPACE_LEN)
406 return -EINVAL;
407
408 if (!lvblen || (lvblen % 8))
409 return -EINVAL;
410
411 if (!try_module_get(THIS_MODULE))
412 return -EINVAL;
413
414 ls = dlm_find_lockspace_name(name, namelen);
415 if (ls) {
416 *lockspace = ls;
417 module_put(THIS_MODULE);
418 return -EEXIST;
419 }
420
David Teigland90135922006-01-20 08:47:07 +0000421 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000422 if (!ls)
423 goto out;
David Teiglande7fd4172006-01-18 09:30:29 +0000424 memcpy(ls->ls_name, name, namelen);
425 ls->ls_namelen = namelen;
David Teiglande7fd4172006-01-18 09:30:29 +0000426 ls->ls_lvblen = lvblen;
427 ls->ls_count = 0;
428 ls->ls_flags = 0;
429
David Teigland3ae1acf2007-05-18 08:59:31 -0500430 /* ls_exflags are forced to match among nodes, and we don't
431 need to require all nodes to have TIMEWARN active */
432 if (flags & DLM_LSFL_TIMEWARN)
433 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
434 ls->ls_exflags = (flags & ~DLM_LSFL_TIMEWARN);
435
David Teigland68c817a2007-01-09 09:41:48 -0600436 size = dlm_config.ci_rsbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000437 ls->ls_rsbtbl_size = size;
438
439 ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL);
440 if (!ls->ls_rsbtbl)
441 goto out_lsfree;
442 for (i = 0; i < size; i++) {
443 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list);
444 INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss);
445 rwlock_init(&ls->ls_rsbtbl[i].lock);
446 }
447
David Teigland68c817a2007-01-09 09:41:48 -0600448 size = dlm_config.ci_lkbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000449 ls->ls_lkbtbl_size = size;
450
451 ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL);
452 if (!ls->ls_lkbtbl)
453 goto out_rsbfree;
454 for (i = 0; i < size; i++) {
455 INIT_LIST_HEAD(&ls->ls_lkbtbl[i].list);
456 rwlock_init(&ls->ls_lkbtbl[i].lock);
457 ls->ls_lkbtbl[i].counter = 1;
458 }
459
David Teigland68c817a2007-01-09 09:41:48 -0600460 size = dlm_config.ci_dirtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000461 ls->ls_dirtbl_size = size;
462
463 ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL);
464 if (!ls->ls_dirtbl)
465 goto out_lkbfree;
466 for (i = 0; i < size; i++) {
467 INIT_LIST_HEAD(&ls->ls_dirtbl[i].list);
468 rwlock_init(&ls->ls_dirtbl[i].lock);
469 }
470
471 INIT_LIST_HEAD(&ls->ls_waiters);
David Teigland90135922006-01-20 08:47:07 +0000472 mutex_init(&ls->ls_waiters_mutex);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500473 INIT_LIST_HEAD(&ls->ls_orphans);
474 mutex_init(&ls->ls_orphans_mutex);
David Teigland3ae1acf2007-05-18 08:59:31 -0500475 INIT_LIST_HEAD(&ls->ls_timeout);
476 mutex_init(&ls->ls_timeout_mutex);
David Teiglande7fd4172006-01-18 09:30:29 +0000477
478 INIT_LIST_HEAD(&ls->ls_nodes);
479 INIT_LIST_HEAD(&ls->ls_nodes_gone);
480 ls->ls_num_nodes = 0;
481 ls->ls_low_nodeid = 0;
482 ls->ls_total_weight = 0;
483 ls->ls_node_array = NULL;
484
485 memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
486 ls->ls_stub_rsb.res_ls = ls;
487
David Teigland5de63192006-07-25 13:44:31 -0500488 ls->ls_debug_rsb_dentry = NULL;
489 ls->ls_debug_waiters_dentry = NULL;
David Teiglande7fd4172006-01-18 09:30:29 +0000490
491 init_waitqueue_head(&ls->ls_uevent_wait);
492 ls->ls_uevent_result = 0;
493
494 ls->ls_recoverd_task = NULL;
David Teigland90135922006-01-20 08:47:07 +0000495 mutex_init(&ls->ls_recoverd_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000496 spin_lock_init(&ls->ls_recover_lock);
David Teigland98f176f2006-11-27 13:19:28 -0600497 spin_lock_init(&ls->ls_rcom_spin);
498 get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
David Teiglande7fd4172006-01-18 09:30:29 +0000499 ls->ls_recover_status = 0;
500 ls->ls_recover_seq = 0;
501 ls->ls_recover_args = NULL;
502 init_rwsem(&ls->ls_in_recovery);
503 INIT_LIST_HEAD(&ls->ls_requestqueue);
David Teigland90135922006-01-20 08:47:07 +0000504 mutex_init(&ls->ls_requestqueue_mutex);
David Teigland597d0ca2006-07-12 16:44:04 -0500505 mutex_init(&ls->ls_clear_proc_locks);
David Teiglande7fd4172006-01-18 09:30:29 +0000506
David Teigland68c817a2007-01-09 09:41:48 -0600507 ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
David Teiglande7fd4172006-01-18 09:30:29 +0000508 if (!ls->ls_recover_buf)
509 goto out_dirfree;
510
511 INIT_LIST_HEAD(&ls->ls_recover_list);
512 spin_lock_init(&ls->ls_recover_list_lock);
513 ls->ls_recover_list_count = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500514 ls->ls_local_handle = ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000515 init_waitqueue_head(&ls->ls_wait_general);
516 INIT_LIST_HEAD(&ls->ls_root_list);
517 init_rwsem(&ls->ls_root_sem);
518
519 down_write(&ls->ls_in_recovery);
520
David Teigland5f88f1e2006-08-24 14:47:20 -0500521 spin_lock(&lslist_lock);
522 list_add(&ls->ls_list, &lslist);
523 spin_unlock(&lslist_lock);
524
525 /* needs to find ls in lslist */
David Teiglande7fd4172006-01-18 09:30:29 +0000526 error = dlm_recoverd_start(ls);
527 if (error) {
528 log_error(ls, "can't start dlm_recoverd %d", error);
David Teigland79d72b52007-05-18 09:02:20 -0500529 goto out_delist;
David Teiglande7fd4172006-01-18 09:30:29 +0000530 }
531
David Teiglande7fd4172006-01-18 09:30:29 +0000532 error = kobject_setup(ls);
533 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500534 goto out_stop;
David Teiglande7fd4172006-01-18 09:30:29 +0000535
536 error = kobject_register(&ls->ls_kobj);
537 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500538 goto out_stop;
539
540 /* let kobject handle freeing of ls if there's an error */
541 do_unreg = 1;
David Teiglande7fd4172006-01-18 09:30:29 +0000542
543 error = do_uevent(ls, 1);
544 if (error)
David Teigland79d72b52007-05-18 09:02:20 -0500545 goto out_stop;
546
547 dlm_create_debug_file(ls);
548
549 log_debug(ls, "join complete");
David Teiglande7fd4172006-01-18 09:30:29 +0000550
551 *lockspace = ls;
552 return 0;
553
David Teigland79d72b52007-05-18 09:02:20 -0500554 out_stop:
David Teigland5f88f1e2006-08-24 14:47:20 -0500555 dlm_recoverd_stop(ls);
David Teigland79d72b52007-05-18 09:02:20 -0500556 out_delist:
David Teiglande7fd4172006-01-18 09:30:29 +0000557 spin_lock(&lslist_lock);
558 list_del(&ls->ls_list);
559 spin_unlock(&lslist_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000560 kfree(ls->ls_recover_buf);
561 out_dirfree:
562 kfree(ls->ls_dirtbl);
563 out_lkbfree:
564 kfree(ls->ls_lkbtbl);
565 out_rsbfree:
566 kfree(ls->ls_rsbtbl);
567 out_lsfree:
David Teigland79d72b52007-05-18 09:02:20 -0500568 if (do_unreg)
569 kobject_unregister(&ls->ls_kobj);
570 else
571 kfree(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000572 out:
573 module_put(THIS_MODULE);
574 return error;
575}
576
577int dlm_new_lockspace(char *name, int namelen, void **lockspace,
578 uint32_t flags, int lvblen)
579{
580 int error = 0;
581
David Teigland90135922006-01-20 08:47:07 +0000582 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000583 if (!ls_count)
584 error = threads_start();
585 if (error)
586 goto out;
587
588 error = new_lockspace(name, namelen, lockspace, flags, lvblen);
589 if (!error)
590 ls_count++;
591 out:
David Teigland90135922006-01-20 08:47:07 +0000592 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000593 return error;
594}
595
596/* Return 1 if the lockspace still has active remote locks,
597 * 2 if the lockspace still has active local locks.
598 */
599static int lockspace_busy(struct dlm_ls *ls)
600{
601 int i, lkb_found = 0;
602 struct dlm_lkb *lkb;
603
604 /* NOTE: We check the lockidtbl here rather than the resource table.
605 This is because there may be LKBs queued as ASTs that have been
606 unlinked from their RSBs and are pending deletion once the AST has
607 been delivered */
608
609 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
610 read_lock(&ls->ls_lkbtbl[i].lock);
611 if (!list_empty(&ls->ls_lkbtbl[i].list)) {
612 lkb_found = 1;
613 list_for_each_entry(lkb, &ls->ls_lkbtbl[i].list,
614 lkb_idtbl_list) {
615 if (!lkb->lkb_nodeid) {
616 read_unlock(&ls->ls_lkbtbl[i].lock);
617 return 2;
618 }
619 }
620 }
621 read_unlock(&ls->ls_lkbtbl[i].lock);
622 }
623 return lkb_found;
624}
625
626static int release_lockspace(struct dlm_ls *ls, int force)
627{
628 struct dlm_lkb *lkb;
629 struct dlm_rsb *rsb;
630 struct list_head *head;
631 int i;
632 int busy = lockspace_busy(ls);
633
634 if (busy > force)
635 return -EBUSY;
636
637 if (force < 3)
638 do_uevent(ls, 0);
639
640 dlm_recoverd_stop(ls);
641
642 remove_lockspace(ls);
643
644 dlm_delete_debug_file(ls);
645
646 dlm_astd_suspend();
647
648 kfree(ls->ls_recover_buf);
649
650 /*
651 * Free direntry structs.
652 */
653
654 dlm_dir_clear(ls);
655 kfree(ls->ls_dirtbl);
656
657 /*
658 * Free all lkb's on lkbtbl[] lists.
659 */
660
661 for (i = 0; i < ls->ls_lkbtbl_size; i++) {
662 head = &ls->ls_lkbtbl[i].list;
663 while (!list_empty(head)) {
664 lkb = list_entry(head->next, struct dlm_lkb,
665 lkb_idtbl_list);
666
667 list_del(&lkb->lkb_idtbl_list);
668
669 dlm_del_ast(lkb);
670
671 if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
672 free_lvb(lkb->lkb_lvbptr);
673
674 free_lkb(lkb);
675 }
676 }
677 dlm_astd_resume();
678
679 kfree(ls->ls_lkbtbl);
680
681 /*
682 * Free all rsb's on rsbtbl[] lists
683 */
684
685 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
686 head = &ls->ls_rsbtbl[i].list;
687 while (!list_empty(head)) {
688 rsb = list_entry(head->next, struct dlm_rsb,
689 res_hashchain);
690
691 list_del(&rsb->res_hashchain);
692 free_rsb(rsb);
693 }
694
695 head = &ls->ls_rsbtbl[i].toss;
696 while (!list_empty(head)) {
697 rsb = list_entry(head->next, struct dlm_rsb,
698 res_hashchain);
699 list_del(&rsb->res_hashchain);
700 free_rsb(rsb);
701 }
702 }
703
704 kfree(ls->ls_rsbtbl);
705
706 /*
707 * Free structures on any other lists
708 */
709
David Teigland2896ee32006-11-27 11:31:22 -0600710 dlm_purge_requestqueue(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000711 kfree(ls->ls_recover_args);
712 dlm_clear_free_entries(ls);
713 dlm_clear_members(ls);
714 dlm_clear_members_gone(ls);
715 kfree(ls->ls_node_array);
716 kobject_unregister(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500717 /* The ls structure will be freed when the kobject is done with */
David Teiglande7fd4172006-01-18 09:30:29 +0000718
David Teigland90135922006-01-20 08:47:07 +0000719 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000720 ls_count--;
721 if (!ls_count)
722 threads_stop();
David Teigland90135922006-01-20 08:47:07 +0000723 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000724
725 module_put(THIS_MODULE);
726 return 0;
727}
728
729/*
730 * Called when a system has released all its locks and is not going to use the
731 * lockspace any longer. We free everything we're managing for this lockspace.
732 * Remaining nodes will go through the recovery process as if we'd died. The
733 * lockspace must continue to function as usual, participating in recoveries,
734 * until this returns.
735 *
736 * Force has 4 possible values:
737 * 0 - don't destroy locksapce if it has any LKBs
738 * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
739 * 2 - destroy lockspace regardless of LKBs
740 * 3 - destroy lockspace as part of a forced shutdown
741 */
742
743int dlm_release_lockspace(void *lockspace, int force)
744{
745 struct dlm_ls *ls;
746
747 ls = dlm_find_lockspace_local(lockspace);
748 if (!ls)
749 return -EINVAL;
750 dlm_put_lockspace(ls);
751 return release_lockspace(ls, force);
752}
753