blob: 78a7c855b06b374f87223b41282cdae1c8f798e8 [file] [log] [blame]
David Teiglande7fd4172006-01-18 09:30:29 +00001/******************************************************************************
2*******************************************************************************
3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
David Teigland60f98d12011-11-02 14:30:58 -05005** Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
David Teiglande7fd4172006-01-18 09:30:29 +00006**
7** This copyrighted material is made available to anyone wishing to use,
8** modify, copy, or redistribute it subject to the terms and conditions
9** of the GNU General Public License v.2.
10**
11*******************************************************************************
12******************************************************************************/
13
Paul Gortmaker7963b8a2016-09-19 16:44:50 -040014#include <linux/module.h>
15
David Teiglande7fd4172006-01-18 09:30:29 +000016#include "dlm_internal.h"
17#include "lockspace.h"
18#include "member.h"
19#include "recoverd.h"
David Teiglande7fd4172006-01-18 09:30:29 +000020#include "dir.h"
21#include "lowcomms.h"
22#include "config.h"
23#include "memory.h"
24#include "lock.h"
David Teiglandc56b39c2006-04-28 10:51:53 -040025#include "recover.h"
David Teigland2896ee32006-11-27 11:31:22 -060026#include "requestqueue.h"
David Teigland0f8e0d92008-08-06 13:30:24 -050027#include "user.h"
David Teigland23e8e1a2011-04-05 13:16:24 -050028#include "ast.h"
David Teiglande7fd4172006-01-18 09:30:29 +000029
David Teiglande7fd4172006-01-18 09:30:29 +000030static int ls_count;
David Teigland90135922006-01-20 08:47:07 +000031static struct mutex ls_lock;
David Teiglande7fd4172006-01-18 09:30:29 +000032static struct list_head lslist;
33static spinlock_t lslist_lock;
34static struct task_struct * scand_task;
35
36
37static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
38{
39 ssize_t ret = len;
Fabian Frederick6edb5682014-06-06 14:38:25 -070040 int n;
41 int rc = kstrtoint(buf, 0, &n);
David Teiglande7fd4172006-01-18 09:30:29 +000042
Fabian Frederick6edb5682014-06-06 14:38:25 -070043 if (rc)
44 return rc;
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000045 ls = dlm_find_lockspace_local(ls->ls_local_handle);
46 if (!ls)
47 return -EINVAL;
48
David Teiglande7fd4172006-01-18 09:30:29 +000049 switch (n) {
50 case 0:
51 dlm_ls_stop(ls);
52 break;
53 case 1:
54 dlm_ls_start(ls);
55 break;
56 default:
57 ret = -EINVAL;
58 }
Patrick Caulfielde2de7f52006-11-06 08:53:28 +000059 dlm_put_lockspace(ls);
David Teiglande7fd4172006-01-18 09:30:29 +000060 return ret;
61}
62
63static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
64{
Fabian Frederick6edb5682014-06-06 14:38:25 -070065 int rc = kstrtoint(buf, 0, &ls->ls_uevent_result);
66
67 if (rc)
68 return rc;
David Teiglande7fd4172006-01-18 09:30:29 +000069 set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
70 wake_up(&ls->ls_uevent_wait);
71 return len;
72}
73
74static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
75{
David Teiglanda1d144c2006-09-06 17:01:40 -050076 return snprintf(buf, PAGE_SIZE, "%u\n", ls->ls_global_id);
David Teiglande7fd4172006-01-18 09:30:29 +000077}
78
79static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
80{
Fabian Frederick6edb5682014-06-06 14:38:25 -070081 int rc = kstrtouint(buf, 0, &ls->ls_global_id);
82
83 if (rc)
84 return rc;
David Teiglande7fd4172006-01-18 09:30:29 +000085 return len;
86}
87
David Teigland48756472012-04-26 15:54:29 -050088static ssize_t dlm_nodir_show(struct dlm_ls *ls, char *buf)
89{
90 return snprintf(buf, PAGE_SIZE, "%u\n", dlm_no_directory(ls));
91}
92
93static ssize_t dlm_nodir_store(struct dlm_ls *ls, const char *buf, size_t len)
94{
Fabian Frederick6edb5682014-06-06 14:38:25 -070095 int val;
96 int rc = kstrtoint(buf, 0, &val);
97
98 if (rc)
99 return rc;
David Teigland48756472012-04-26 15:54:29 -0500100 if (val == 1)
101 set_bit(LSFL_NODIR, &ls->ls_flags);
102 return len;
103}
104
David Teiglandc56b39c2006-04-28 10:51:53 -0400105static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
106{
107 uint32_t status = dlm_recover_status(ls);
David Teiglanda1d144c2006-09-06 17:01:40 -0500108 return snprintf(buf, PAGE_SIZE, "%x\n", status);
David Teiglandc56b39c2006-04-28 10:51:53 -0400109}
110
David Teiglandfaa0f262006-08-08 17:08:42 -0500111static ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf)
112{
David Teiglanda1d144c2006-09-06 17:01:40 -0500113 return snprintf(buf, PAGE_SIZE, "%d\n", ls->ls_recover_nodeid);
David Teiglandfaa0f262006-08-08 17:08:42 -0500114}
115
David Teiglande7fd4172006-01-18 09:30:29 +0000116struct dlm_attr {
117 struct attribute attr;
118 ssize_t (*show)(struct dlm_ls *, char *);
119 ssize_t (*store)(struct dlm_ls *, const char *, size_t);
120};
121
122static struct dlm_attr dlm_attr_control = {
123 .attr = {.name = "control", .mode = S_IWUSR},
124 .store = dlm_control_store
125};
126
127static struct dlm_attr dlm_attr_event = {
128 .attr = {.name = "event_done", .mode = S_IWUSR},
129 .store = dlm_event_store
130};
131
132static struct dlm_attr dlm_attr_id = {
133 .attr = {.name = "id", .mode = S_IRUGO | S_IWUSR},
134 .show = dlm_id_show,
135 .store = dlm_id_store
136};
137
David Teigland48756472012-04-26 15:54:29 -0500138static struct dlm_attr dlm_attr_nodir = {
139 .attr = {.name = "nodir", .mode = S_IRUGO | S_IWUSR},
140 .show = dlm_nodir_show,
141 .store = dlm_nodir_store
142};
143
David Teiglandc56b39c2006-04-28 10:51:53 -0400144static struct dlm_attr dlm_attr_recover_status = {
145 .attr = {.name = "recover_status", .mode = S_IRUGO},
146 .show = dlm_recover_status_show
147};
148
David Teiglandfaa0f262006-08-08 17:08:42 -0500149static struct dlm_attr dlm_attr_recover_nodeid = {
150 .attr = {.name = "recover_nodeid", .mode = S_IRUGO},
151 .show = dlm_recover_nodeid_show
152};
153
David Teiglande7fd4172006-01-18 09:30:29 +0000154static struct attribute *dlm_attrs[] = {
155 &dlm_attr_control.attr,
156 &dlm_attr_event.attr,
157 &dlm_attr_id.attr,
David Teigland48756472012-04-26 15:54:29 -0500158 &dlm_attr_nodir.attr,
David Teiglandc56b39c2006-04-28 10:51:53 -0400159 &dlm_attr_recover_status.attr,
David Teiglandfaa0f262006-08-08 17:08:42 -0500160 &dlm_attr_recover_nodeid.attr,
David Teiglande7fd4172006-01-18 09:30:29 +0000161 NULL,
162};
163
164static ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr,
165 char *buf)
166{
167 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
168 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
169 return a->show ? a->show(ls, buf) : 0;
170}
171
172static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
173 const char *buf, size_t len)
174{
175 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
176 struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
177 return a->store ? a->store(ls, buf, len) : len;
178}
179
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000180static void lockspace_kobj_release(struct kobject *k)
181{
182 struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj);
183 kfree(ls);
184}
185
Emese Revfy52cf25d2010-01-19 02:58:23 +0100186static const struct sysfs_ops dlm_attr_ops = {
David Teiglande7fd4172006-01-18 09:30:29 +0000187 .show = dlm_attr_show,
188 .store = dlm_attr_store,
189};
190
191static struct kobj_type dlm_ktype = {
192 .default_attrs = dlm_attrs,
193 .sysfs_ops = &dlm_attr_ops,
Patrick Caulfieldba542e32006-11-02 14:41:23 +0000194 .release = lockspace_kobj_release,
David Teiglande7fd4172006-01-18 09:30:29 +0000195};
196
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100197static struct kset *dlm_kset;
David Teiglande7fd4172006-01-18 09:30:29 +0000198
David Teiglande7fd4172006-01-18 09:30:29 +0000199static int do_uevent(struct dlm_ls *ls, int in)
200{
201 int error;
202
203 if (in)
204 kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
205 else
206 kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
207
David Teigland075f0172014-02-14 11:54:44 -0600208 log_rinfo(ls, "%s the lockspace group...", in ? "joining" : "leaving");
David Teigland8b0e7b22007-05-18 09:03:35 -0500209
210 /* dlm_controld will see the uevent, do the necessary group management
211 and then write to sysfs to wake us */
212
David Teiglande7fd4172006-01-18 09:30:29 +0000213 error = wait_event_interruptible(ls->ls_uevent_wait,
214 test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
David Teigland8b0e7b22007-05-18 09:03:35 -0500215
David Teigland075f0172014-02-14 11:54:44 -0600216 log_rinfo(ls, "group event done %d %d", error, ls->ls_uevent_result);
David Teigland8b0e7b22007-05-18 09:03:35 -0500217
David Teiglande7fd4172006-01-18 09:30:29 +0000218 if (error)
219 goto out;
220
221 error = ls->ls_uevent_result;
222 out:
David Teigland8b0e7b22007-05-18 09:03:35 -0500223 if (error)
224 log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
225 error, ls->ls_uevent_result);
David Teiglande7fd4172006-01-18 09:30:29 +0000226 return error;
227}
228
Steven Whitehouseb4a5d4b2010-02-17 09:41:34 +0000229static int dlm_uevent(struct kset *kset, struct kobject *kobj,
230 struct kobj_uevent_env *env)
231{
232 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
233
234 add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
235 return 0;
236}
237
Bhumika Goyal417f7c52017-07-28 18:49:17 +0530238static const struct kset_uevent_ops dlm_uevent_ops = {
Steven Whitehouseb4a5d4b2010-02-17 09:41:34 +0000239 .uevent = dlm_uevent,
240};
David Teiglande7fd4172006-01-18 09:30:29 +0000241
Denis Cheng30727172008-02-02 01:53:46 +0800242int __init dlm_lockspace_init(void)
David Teiglande7fd4172006-01-18 09:30:29 +0000243{
David Teiglande7fd4172006-01-18 09:30:29 +0000244 ls_count = 0;
David Teigland90135922006-01-20 08:47:07 +0000245 mutex_init(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000246 INIT_LIST_HEAD(&lslist);
247 spin_lock_init(&lslist_lock);
248
Steven Whitehouseb4a5d4b2010-02-17 09:41:34 +0000249 dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100250 if (!dlm_kset) {
Harvey Harrison8e24eea2008-04-30 00:55:09 -0700251 printk(KERN_WARNING "%s: can not create kset\n", __func__);
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100252 return -ENOMEM;
253 }
254 return 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000255}
256
257void dlm_lockspace_exit(void)
258{
Greg Kroah-Hartmand4059362007-10-29 20:13:17 +0100259 kset_unregister(dlm_kset);
David Teiglande7fd4172006-01-18 09:30:29 +0000260}
261
David Teiglandc1dcf652008-08-18 14:03:25 -0500262static struct dlm_ls *find_ls_to_scan(void)
David Teiglande7fd4172006-01-18 09:30:29 +0000263{
264 struct dlm_ls *ls;
265
David Teiglandc1dcf652008-08-18 14:03:25 -0500266 spin_lock(&lslist_lock);
267 list_for_each_entry(ls, &lslist, ls_list) {
268 if (time_after_eq(jiffies, ls->ls_scan_time +
269 dlm_config.ci_scan_secs * HZ)) {
270 spin_unlock(&lslist_lock);
271 return ls;
272 }
273 }
274 spin_unlock(&lslist_lock);
275 return NULL;
276}
277
278static int dlm_scand(void *data)
279{
280 struct dlm_ls *ls;
David Teiglandc1dcf652008-08-18 14:03:25 -0500281
David Teiglande7fd4172006-01-18 09:30:29 +0000282 while (!kthread_should_stop()) {
David Teiglandc1dcf652008-08-18 14:03:25 -0500283 ls = find_ls_to_scan();
284 if (ls) {
David Teigland85e86ed2007-05-18 08:58:15 -0500285 if (dlm_lock_recovery_try(ls)) {
David Teiglandc1dcf652008-08-18 14:03:25 -0500286 ls->ls_scan_time = jiffies;
David Teigland85e86ed2007-05-18 08:58:15 -0500287 dlm_scan_rsbs(ls);
David Teigland3ae1acf2007-05-18 08:59:31 -0500288 dlm_scan_timeout(ls);
David Teiglandc6ff6692011-03-28 14:17:26 -0500289 dlm_scan_waiters(ls);
David Teigland85e86ed2007-05-18 08:58:15 -0500290 dlm_unlock_recovery(ls);
David Teiglandc1dcf652008-08-18 14:03:25 -0500291 } else {
292 ls->ls_scan_time += HZ;
David Teigland85e86ed2007-05-18 08:58:15 -0500293 }
David Teiglandc6ff6692011-03-28 14:17:26 -0500294 continue;
David Teigland85e86ed2007-05-18 08:58:15 -0500295 }
David Teiglandc6ff6692011-03-28 14:17:26 -0500296 schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
David Teiglande7fd4172006-01-18 09:30:29 +0000297 }
298 return 0;
299}
300
301static int dlm_scand_start(void)
302{
303 struct task_struct *p;
304 int error = 0;
305
306 p = kthread_run(dlm_scand, NULL, "dlm_scand");
307 if (IS_ERR(p))
308 error = PTR_ERR(p);
309 else
310 scand_task = p;
311 return error;
312}
313
314static void dlm_scand_stop(void)
315{
316 kthread_stop(scand_task);
317}
318
David Teiglande7fd4172006-01-18 09:30:29 +0000319struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
320{
321 struct dlm_ls *ls;
322
323 spin_lock(&lslist_lock);
324
325 list_for_each_entry(ls, &lslist, ls_list) {
326 if (ls->ls_global_id == id) {
327 ls->ls_count++;
328 goto out;
329 }
330 }
331 ls = NULL;
332 out:
333 spin_unlock(&lslist_lock);
334 return ls;
335}
336
David Teigland597d0ca2006-07-12 16:44:04 -0500337struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000338{
David Teigland597d0ca2006-07-12 16:44:04 -0500339 struct dlm_ls *ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000340
341 spin_lock(&lslist_lock);
David Teigland597d0ca2006-07-12 16:44:04 -0500342 list_for_each_entry(ls, &lslist, ls_list) {
343 if (ls->ls_local_handle == lockspace) {
344 ls->ls_count++;
345 goto out;
346 }
347 }
348 ls = NULL;
349 out:
350 spin_unlock(&lslist_lock);
351 return ls;
352}
353
354struct dlm_ls *dlm_find_lockspace_device(int minor)
355{
356 struct dlm_ls *ls;
357
358 spin_lock(&lslist_lock);
359 list_for_each_entry(ls, &lslist, ls_list) {
360 if (ls->ls_device.minor == minor) {
361 ls->ls_count++;
362 goto out;
363 }
364 }
365 ls = NULL;
366 out:
David Teiglande7fd4172006-01-18 09:30:29 +0000367 spin_unlock(&lslist_lock);
368 return ls;
369}
370
371void dlm_put_lockspace(struct dlm_ls *ls)
372{
373 spin_lock(&lslist_lock);
374 ls->ls_count--;
375 spin_unlock(&lslist_lock);
376}
377
378static void remove_lockspace(struct dlm_ls *ls)
379{
380 for (;;) {
381 spin_lock(&lslist_lock);
382 if (ls->ls_count == 0) {
David Teigland0f8e0d92008-08-06 13:30:24 -0500383 WARN_ON(ls->ls_create_count != 0);
David Teiglande7fd4172006-01-18 09:30:29 +0000384 list_del(&ls->ls_list);
385 spin_unlock(&lslist_lock);
386 return;
387 }
388 spin_unlock(&lslist_lock);
389 ssleep(1);
390 }
391}
392
393static int threads_start(void)
394{
395 int error;
396
David Teiglande7fd4172006-01-18 09:30:29 +0000397 error = dlm_scand_start();
398 if (error) {
399 log_print("cannot start dlm_scand thread %d", error);
David Teigland23e8e1a2011-04-05 13:16:24 -0500400 goto fail;
David Teiglande7fd4172006-01-18 09:30:29 +0000401 }
402
403 /* Thread for sending/receiving messages for all lockspace's */
404 error = dlm_lowcomms_start();
405 if (error) {
406 log_print("cannot start dlm lowcomms %d", error);
407 goto scand_fail;
408 }
409
410 return 0;
411
412 scand_fail:
413 dlm_scand_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000414 fail:
415 return error;
416}
417
418static void threads_stop(void)
419{
420 dlm_scand_stop();
421 dlm_lowcomms_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000422}
423
David Teigland60f98d12011-11-02 14:30:58 -0500424static int new_lockspace(const char *name, const char *cluster,
425 uint32_t flags, int lvblen,
426 const struct dlm_lockspace_ops *ops, void *ops_arg,
427 int *ops_result, dlm_lockspace_t **lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000428{
429 struct dlm_ls *ls;
David Teigland0f8e0d92008-08-06 13:30:24 -0500430 int i, size, error;
David Teigland79d72b52007-05-18 09:02:20 -0500431 int do_unreg = 0;
David Teigland60f98d12011-11-02 14:30:58 -0500432 int namelen = strlen(name);
David Teiglande7fd4172006-01-18 09:30:29 +0000433
434 if (namelen > DLM_LOCKSPACE_LEN)
435 return -EINVAL;
436
437 if (!lvblen || (lvblen % 8))
438 return -EINVAL;
439
440 if (!try_module_get(THIS_MODULE))
441 return -EINVAL;
442
David Teiglanddc68c7e2008-08-18 11:43:30 -0500443 if (!dlm_user_daemon_available()) {
David Teigland60f98d12011-11-02 14:30:58 -0500444 log_print("dlm user daemon not available");
445 error = -EUNATCH;
446 goto out;
447 }
448
449 if (ops && ops_result) {
450 if (!dlm_config.ci_recover_callbacks)
451 *ops_result = -EOPNOTSUPP;
452 else
453 *ops_result = 0;
454 }
455
Zhu Lingshan3b0e7612017-07-11 09:26:55 -0500456 if (!cluster)
457 log_print("dlm cluster name '%s' is being used without an application provided cluster name",
458 dlm_config.ci_cluster_name);
459
David Teigland60f98d12011-11-02 14:30:58 -0500460 if (dlm_config.ci_recover_callbacks && cluster &&
461 strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) {
Gang He8e174372017-05-18 10:42:12 +0800462 log_print("dlm cluster name '%s' does not match "
463 "the application cluster name '%s'",
David Teigland60f98d12011-11-02 14:30:58 -0500464 dlm_config.ci_cluster_name, cluster);
465 error = -EBADR;
466 goto out;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500467 }
468
David Teigland0f8e0d92008-08-06 13:30:24 -0500469 error = 0;
470
471 spin_lock(&lslist_lock);
472 list_for_each_entry(ls, &lslist, ls_list) {
473 WARN_ON(ls->ls_create_count <= 0);
474 if (ls->ls_namelen != namelen)
475 continue;
476 if (memcmp(ls->ls_name, name, namelen))
477 continue;
478 if (flags & DLM_LSFL_NEWEXCL) {
479 error = -EEXIST;
480 break;
481 }
482 ls->ls_create_count++;
David Teigland8511a272009-04-08 15:38:43 -0500483 *lockspace = ls;
484 error = 1;
David Teigland0f8e0d92008-08-06 13:30:24 -0500485 break;
David Teiglande7fd4172006-01-18 09:30:29 +0000486 }
David Teigland0f8e0d92008-08-06 13:30:24 -0500487 spin_unlock(&lslist_lock);
488
David Teigland0f8e0d92008-08-06 13:30:24 -0500489 if (error)
David Teigland8511a272009-04-08 15:38:43 -0500490 goto out;
David Teigland0f8e0d92008-08-06 13:30:24 -0500491
492 error = -ENOMEM;
David Teiglande7fd4172006-01-18 09:30:29 +0000493
David Teigland573c24c2009-11-30 16:34:43 -0600494 ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_NOFS);
David Teiglande7fd4172006-01-18 09:30:29 +0000495 if (!ls)
496 goto out;
David Teiglande7fd4172006-01-18 09:30:29 +0000497 memcpy(ls->ls_name, name, namelen);
498 ls->ls_namelen = namelen;
David Teiglande7fd4172006-01-18 09:30:29 +0000499 ls->ls_lvblen = lvblen;
500 ls->ls_count = 0;
501 ls->ls_flags = 0;
David Teiglandc1dcf652008-08-18 14:03:25 -0500502 ls->ls_scan_time = jiffies;
David Teiglande7fd4172006-01-18 09:30:29 +0000503
David Teigland60f98d12011-11-02 14:30:58 -0500504 if (ops && dlm_config.ci_recover_callbacks) {
505 ls->ls_ops = ops;
506 ls->ls_ops_arg = ops_arg;
507 }
508
David Teigland3ae1acf2007-05-18 08:59:31 -0500509 if (flags & DLM_LSFL_TIMEWARN)
510 set_bit(LSFL_TIMEWARN, &ls->ls_flags);
David Teigland3ae1acf2007-05-18 08:59:31 -0500511
David Teiglandfad59c12007-06-11 10:47:18 -0500512 /* ls_exflags are forced to match among nodes, and we don't
David Teigland0f8e0d92008-08-06 13:30:24 -0500513 need to require all nodes to have some flags set */
514 ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
515 DLM_LSFL_NEWEXCL));
David Teiglandfad59c12007-06-11 10:47:18 -0500516
David Teigland68c817a2007-01-09 09:41:48 -0600517 size = dlm_config.ci_rsbtbl_size;
David Teiglande7fd4172006-01-18 09:30:29 +0000518 ls->ls_rsbtbl_size = size;
519
Bryn M. Reevesc282af42011-07-01 15:49:23 -0500520 ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
David Teiglande7fd4172006-01-18 09:30:29 +0000521 if (!ls->ls_rsbtbl)
522 goto out_lsfree;
523 for (i = 0; i < size; i++) {
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500524 ls->ls_rsbtbl[i].keep.rb_node = NULL;
525 ls->ls_rsbtbl[i].toss.rb_node = NULL;
David Teiglandc7be7612009-01-07 16:50:41 -0600526 spin_lock_init(&ls->ls_rsbtbl[i].lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000527 }
528
David Teigland05c32f42012-06-14 12:17:32 -0500529 spin_lock_init(&ls->ls_remove_spin);
530
531 for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
532 ls->ls_remove_names[i] = kzalloc(DLM_RESNAME_MAXLEN+1,
533 GFP_KERNEL);
534 if (!ls->ls_remove_names[i])
535 goto out_rsbtbl;
536 }
537
David Teigland3d6aa672011-07-06 17:00:54 -0500538 idr_init(&ls->ls_lkbidr);
539 spin_lock_init(&ls->ls_lkbidr_spin);
David Teiglande7fd4172006-01-18 09:30:29 +0000540
David Teiglande7fd4172006-01-18 09:30:29 +0000541 INIT_LIST_HEAD(&ls->ls_waiters);
David Teigland90135922006-01-20 08:47:07 +0000542 mutex_init(&ls->ls_waiters_mutex);
David Teiglandef0c2bb2007-03-28 09:56:46 -0500543 INIT_LIST_HEAD(&ls->ls_orphans);
544 mutex_init(&ls->ls_orphans_mutex);
David Teigland3ae1acf2007-05-18 08:59:31 -0500545 INIT_LIST_HEAD(&ls->ls_timeout);
546 mutex_init(&ls->ls_timeout_mutex);
David Teiglande7fd4172006-01-18 09:30:29 +0000547
David Teigland3881ac02011-07-07 14:05:03 -0500548 INIT_LIST_HEAD(&ls->ls_new_rsb);
549 spin_lock_init(&ls->ls_new_rsb_spin);
550
David Teiglande7fd4172006-01-18 09:30:29 +0000551 INIT_LIST_HEAD(&ls->ls_nodes);
552 INIT_LIST_HEAD(&ls->ls_nodes_gone);
553 ls->ls_num_nodes = 0;
554 ls->ls_low_nodeid = 0;
555 ls->ls_total_weight = 0;
556 ls->ls_node_array = NULL;
557
558 memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
559 ls->ls_stub_rsb.res_ls = ls;
560
David Teigland5de63192006-07-25 13:44:31 -0500561 ls->ls_debug_rsb_dentry = NULL;
562 ls->ls_debug_waiters_dentry = NULL;
David Teiglande7fd4172006-01-18 09:30:29 +0000563
564 init_waitqueue_head(&ls->ls_uevent_wait);
565 ls->ls_uevent_result = 0;
David Teigland8b0e7b22007-05-18 09:03:35 -0500566 init_completion(&ls->ls_members_done);
567 ls->ls_members_result = -1;
David Teiglande7fd4172006-01-18 09:30:29 +0000568
David Teigland23e8e1a2011-04-05 13:16:24 -0500569 mutex_init(&ls->ls_cb_mutex);
570 INIT_LIST_HEAD(&ls->ls_cb_delay);
571
David Teiglande7fd4172006-01-18 09:30:29 +0000572 ls->ls_recoverd_task = NULL;
David Teigland90135922006-01-20 08:47:07 +0000573 mutex_init(&ls->ls_recoverd_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000574 spin_lock_init(&ls->ls_recover_lock);
David Teigland98f176f2006-11-27 13:19:28 -0600575 spin_lock_init(&ls->ls_rcom_spin);
576 get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
David Teiglande7fd4172006-01-18 09:30:29 +0000577 ls->ls_recover_status = 0;
578 ls->ls_recover_seq = 0;
579 ls->ls_recover_args = NULL;
580 init_rwsem(&ls->ls_in_recovery);
David Teiglandc36258b2007-09-27 15:53:38 -0500581 init_rwsem(&ls->ls_recv_active);
David Teiglande7fd4172006-01-18 09:30:29 +0000582 INIT_LIST_HEAD(&ls->ls_requestqueue);
David Teigland90135922006-01-20 08:47:07 +0000583 mutex_init(&ls->ls_requestqueue_mutex);
David Teigland597d0ca2006-07-12 16:44:04 -0500584 mutex_init(&ls->ls_clear_proc_locks);
David Teiglande7fd4172006-01-18 09:30:29 +0000585
David Teigland573c24c2009-11-30 16:34:43 -0600586 ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
David Teiglande7fd4172006-01-18 09:30:29 +0000587 if (!ls->ls_recover_buf)
David Teigland05c32f42012-06-14 12:17:32 -0500588 goto out_lkbidr;
David Teiglande7fd4172006-01-18 09:30:29 +0000589
David Teigland757a4272011-10-20 13:26:28 -0500590 ls->ls_slot = 0;
591 ls->ls_num_slots = 0;
592 ls->ls_slots_size = 0;
593 ls->ls_slots = NULL;
594
David Teiglande7fd4172006-01-18 09:30:29 +0000595 INIT_LIST_HEAD(&ls->ls_recover_list);
596 spin_lock_init(&ls->ls_recover_list_lock);
David Teigland1d7c4842012-05-15 16:07:49 -0500597 idr_init(&ls->ls_recover_idr);
598 spin_lock_init(&ls->ls_recover_idr_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000599 ls->ls_recover_list_count = 0;
David Teigland597d0ca2006-07-12 16:44:04 -0500600 ls->ls_local_handle = ls;
David Teiglande7fd4172006-01-18 09:30:29 +0000601 init_waitqueue_head(&ls->ls_wait_general);
602 INIT_LIST_HEAD(&ls->ls_root_list);
603 init_rwsem(&ls->ls_root_sem);
604
David Teigland5f88f1e2006-08-24 14:47:20 -0500605 spin_lock(&lslist_lock);
David Teigland0f8e0d92008-08-06 13:30:24 -0500606 ls->ls_create_count = 1;
David Teigland5f88f1e2006-08-24 14:47:20 -0500607 list_add(&ls->ls_list, &lslist);
608 spin_unlock(&lslist_lock);
609
David Teigland23e8e1a2011-04-05 13:16:24 -0500610 if (flags & DLM_LSFL_FS) {
611 error = dlm_callback_start(ls);
612 if (error) {
613 log_error(ls, "can't start dlm_callback %d", error);
614 goto out_delist;
615 }
616 }
617
David Teigland475f2302012-08-02 11:08:21 -0500618 init_waitqueue_head(&ls->ls_recover_lock_wait);
619
620 /*
621 * Once started, dlm_recoverd first looks for ls in lslist, then
622 * initializes ls_in_recovery as locked in "down" mode. We need
623 * to wait for the wakeup from dlm_recoverd because in_recovery
624 * has to start out in down mode.
625 */
626
David Teiglande7fd4172006-01-18 09:30:29 +0000627 error = dlm_recoverd_start(ls);
628 if (error) {
629 log_error(ls, "can't start dlm_recoverd %d", error);
David Teigland23e8e1a2011-04-05 13:16:24 -0500630 goto out_callback;
David Teiglande7fd4172006-01-18 09:30:29 +0000631 }
632
David Teigland475f2302012-08-02 11:08:21 -0500633 wait_event(ls->ls_recover_lock_wait,
634 test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
635
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400636 ls->ls_kobj.kset = dlm_kset;
637 error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
638 "%s", ls->ls_name);
David Teiglande7fd4172006-01-18 09:30:29 +0000639 if (error)
David Teigland23e8e1a2011-04-05 13:16:24 -0500640 goto out_recoverd;
Greg Kroah-Hartman901195e2007-12-17 15:54:39 -0400641 kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
David Teigland79d72b52007-05-18 09:02:20 -0500642
643 /* let kobject handle freeing of ls if there's an error */
644 do_unreg = 1;
David Teiglande7fd4172006-01-18 09:30:29 +0000645
David Teigland8b0e7b22007-05-18 09:03:35 -0500646 /* This uevent triggers dlm_controld in userspace to add us to the
647 group of nodes that are members of this lockspace (managed by the
648 cluster infrastructure.) Once it's done that, it tells us who the
649 current lockspace members are (via configfs) and then tells the
650 lockspace to start running (via sysfs) in dlm_ls_start(). */
651
David Teiglande7fd4172006-01-18 09:30:29 +0000652 error = do_uevent(ls, 1);
653 if (error)
David Teigland23e8e1a2011-04-05 13:16:24 -0500654 goto out_recoverd;
David Teigland79d72b52007-05-18 09:02:20 -0500655
David Teigland8b0e7b22007-05-18 09:03:35 -0500656 wait_for_completion(&ls->ls_members_done);
657 error = ls->ls_members_result;
658 if (error)
659 goto out_members;
660
David Teigland79d72b52007-05-18 09:02:20 -0500661 dlm_create_debug_file(ls);
662
David Teigland075f0172014-02-14 11:54:44 -0600663 log_rinfo(ls, "join complete");
David Teiglande7fd4172006-01-18 09:30:29 +0000664 *lockspace = ls;
665 return 0;
666
David Teigland8b0e7b22007-05-18 09:03:35 -0500667 out_members:
668 do_uevent(ls, 0);
669 dlm_clear_members(ls);
670 kfree(ls->ls_node_array);
David Teigland23e8e1a2011-04-05 13:16:24 -0500671 out_recoverd:
David Teigland5f88f1e2006-08-24 14:47:20 -0500672 dlm_recoverd_stop(ls);
David Teigland23e8e1a2011-04-05 13:16:24 -0500673 out_callback:
674 dlm_callback_stop(ls);
David Teigland79d72b52007-05-18 09:02:20 -0500675 out_delist:
David Teiglande7fd4172006-01-18 09:30:29 +0000676 spin_lock(&lslist_lock);
677 list_del(&ls->ls_list);
678 spin_unlock(&lslist_lock);
David Teigland1d7c4842012-05-15 16:07:49 -0500679 idr_destroy(&ls->ls_recover_idr);
David Teiglande7fd4172006-01-18 09:30:29 +0000680 kfree(ls->ls_recover_buf);
David Teigland05c32f42012-06-14 12:17:32 -0500681 out_lkbidr:
David Teigland3d6aa672011-07-06 17:00:54 -0500682 idr_destroy(&ls->ls_lkbidr);
David Teigland05c32f42012-06-14 12:17:32 -0500683 for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
684 if (ls->ls_remove_names[i])
685 kfree(ls->ls_remove_names[i]);
686 }
687 out_rsbtbl:
Bryn M. Reevesc282af42011-07-01 15:49:23 -0500688 vfree(ls->ls_rsbtbl);
David Teiglande7fd4172006-01-18 09:30:29 +0000689 out_lsfree:
David Teigland79d72b52007-05-18 09:02:20 -0500690 if (do_unreg)
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800691 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500692 else
693 kfree(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000694 out:
695 module_put(THIS_MODULE);
696 return error;
697}
698
David Teigland60f98d12011-11-02 14:30:58 -0500699int dlm_new_lockspace(const char *name, const char *cluster,
700 uint32_t flags, int lvblen,
701 const struct dlm_lockspace_ops *ops, void *ops_arg,
702 int *ops_result, dlm_lockspace_t **lockspace)
David Teiglande7fd4172006-01-18 09:30:29 +0000703{
704 int error = 0;
705
David Teigland90135922006-01-20 08:47:07 +0000706 mutex_lock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000707 if (!ls_count)
708 error = threads_start();
709 if (error)
710 goto out;
711
David Teigland60f98d12011-11-02 14:30:58 -0500712 error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg,
713 ops_result, lockspace);
David Teiglande7fd4172006-01-18 09:30:29 +0000714 if (!error)
715 ls_count++;
David Teigland8511a272009-04-08 15:38:43 -0500716 if (error > 0)
717 error = 0;
718 if (!ls_count)
David Teigland8b0e7b22007-05-18 09:03:35 -0500719 threads_stop();
David Teiglande7fd4172006-01-18 09:30:29 +0000720 out:
David Teigland90135922006-01-20 08:47:07 +0000721 mutex_unlock(&ls_lock);
David Teiglande7fd4172006-01-18 09:30:29 +0000722 return error;
723}
724
David Teigland3d6aa672011-07-06 17:00:54 -0500725static int lkb_idr_is_local(int id, void *p, void *data)
David Teiglande7fd4172006-01-18 09:30:29 +0000726{
David Teigland3d6aa672011-07-06 17:00:54 -0500727 struct dlm_lkb *lkb = p;
David Teiglande7fd4172006-01-18 09:30:29 +0000728
Bart Van Asschea97f4a62013-10-16 14:20:25 +0200729 return lkb->lkb_nodeid == 0 && lkb->lkb_grmode != DLM_LOCK_IV;
David Teigland3d6aa672011-07-06 17:00:54 -0500730}
David Teiglande7fd4172006-01-18 09:30:29 +0000731
David Teigland3d6aa672011-07-06 17:00:54 -0500732static int lkb_idr_is_any(int id, void *p, void *data)
733{
734 return 1;
735}
736
737static int lkb_idr_free(int id, void *p, void *data)
738{
739 struct dlm_lkb *lkb = p;
740
David Teigland3d6aa672011-07-06 17:00:54 -0500741 if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
742 dlm_free_lvb(lkb->lkb_lvbptr);
743
744 dlm_free_lkb(lkb);
745 return 0;
746}
747
748/* NOTE: We check the lkbidr here rather than the resource table.
749 This is because there may be LKBs queued as ASTs that have been unlinked
750 from their RSBs and are pending deletion once the AST has been delivered */
751
752static int lockspace_busy(struct dlm_ls *ls, int force)
753{
754 int rv;
755
756 spin_lock(&ls->ls_lkbidr_spin);
757 if (force == 0) {
758 rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls);
759 } else if (force == 1) {
760 rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls);
761 } else {
762 rv = 0;
David Teiglande7fd4172006-01-18 09:30:29 +0000763 }
David Teigland3d6aa672011-07-06 17:00:54 -0500764 spin_unlock(&ls->ls_lkbidr_spin);
765 return rv;
David Teiglande7fd4172006-01-18 09:30:29 +0000766}
767
768static int release_lockspace(struct dlm_ls *ls, int force)
769{
David Teiglande7fd4172006-01-18 09:30:29 +0000770 struct dlm_rsb *rsb;
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500771 struct rb_node *n;
David Teigland0f8e0d92008-08-06 13:30:24 -0500772 int i, busy, rv;
David Teiglande7fd4172006-01-18 09:30:29 +0000773
David Teigland3d6aa672011-07-06 17:00:54 -0500774 busy = lockspace_busy(ls, force);
David Teigland0f8e0d92008-08-06 13:30:24 -0500775
776 spin_lock(&lslist_lock);
777 if (ls->ls_create_count == 1) {
David Teigland3d6aa672011-07-06 17:00:54 -0500778 if (busy) {
David Teigland0f8e0d92008-08-06 13:30:24 -0500779 rv = -EBUSY;
David Teigland3d6aa672011-07-06 17:00:54 -0500780 } else {
David Teigland0f8e0d92008-08-06 13:30:24 -0500781 /* remove_lockspace takes ls off lslist */
782 ls->ls_create_count = 0;
783 rv = 0;
784 }
785 } else if (ls->ls_create_count > 1) {
786 rv = --ls->ls_create_count;
787 } else {
788 rv = -EINVAL;
789 }
790 spin_unlock(&lslist_lock);
791
792 if (rv) {
793 log_debug(ls, "release_lockspace no remove %d", rv);
794 return rv;
795 }
796
797 dlm_device_deregister(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000798
David Teiglanddc68c7e2008-08-18 11:43:30 -0500799 if (force < 3 && dlm_user_daemon_available())
David Teiglande7fd4172006-01-18 09:30:29 +0000800 do_uevent(ls, 0);
801
802 dlm_recoverd_stop(ls);
803
David Teigland23e8e1a2011-04-05 13:16:24 -0500804 dlm_callback_stop(ls);
805
David Teiglande7fd4172006-01-18 09:30:29 +0000806 remove_lockspace(ls);
807
808 dlm_delete_debug_file(ls);
809
David Teiglande7fd4172006-01-18 09:30:29 +0000810 kfree(ls->ls_recover_buf);
811
812 /*
David Teigland3d6aa672011-07-06 17:00:54 -0500813 * Free all lkb's in idr
David Teiglande7fd4172006-01-18 09:30:29 +0000814 */
815
David Teigland3d6aa672011-07-06 17:00:54 -0500816 idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls);
David Teigland3d6aa672011-07-06 17:00:54 -0500817 idr_destroy(&ls->ls_lkbidr);
David Teiglande7fd4172006-01-18 09:30:29 +0000818
David Teiglande7fd4172006-01-18 09:30:29 +0000819 /*
820 * Free all rsb's on rsbtbl[] lists
821 */
822
823 for (i = 0; i < ls->ls_rsbtbl_size; i++) {
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500824 while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) {
825 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
826 rb_erase(n, &ls->ls_rsbtbl[i].keep);
David Teigland52bda2b2007-11-07 09:06:49 -0600827 dlm_free_rsb(rsb);
David Teiglande7fd4172006-01-18 09:30:29 +0000828 }
829
Bob Peterson9beb3bf2011-10-26 15:24:55 -0500830 while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) {
831 rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
832 rb_erase(n, &ls->ls_rsbtbl[i].toss);
David Teigland52bda2b2007-11-07 09:06:49 -0600833 dlm_free_rsb(rsb);
David Teiglande7fd4172006-01-18 09:30:29 +0000834 }
835 }
836
Bryn M. Reevesc282af42011-07-01 15:49:23 -0500837 vfree(ls->ls_rsbtbl);
David Teiglande7fd4172006-01-18 09:30:29 +0000838
David Teigland05c32f42012-06-14 12:17:32 -0500839 for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++)
840 kfree(ls->ls_remove_names[i]);
841
David Teigland3881ac02011-07-07 14:05:03 -0500842 while (!list_empty(&ls->ls_new_rsb)) {
843 rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
844 res_hashchain);
845 list_del(&rsb->res_hashchain);
846 dlm_free_rsb(rsb);
847 }
848
David Teiglande7fd4172006-01-18 09:30:29 +0000849 /*
850 * Free structures on any other lists
851 */
852
David Teigland2896ee32006-11-27 11:31:22 -0600853 dlm_purge_requestqueue(ls);
David Teiglande7fd4172006-01-18 09:30:29 +0000854 kfree(ls->ls_recover_args);
David Teiglande7fd4172006-01-18 09:30:29 +0000855 dlm_clear_members(ls);
856 dlm_clear_members_gone(ls);
857 kfree(ls->ls_node_array);
David Teigland075f0172014-02-14 11:54:44 -0600858 log_rinfo(ls, "release_lockspace final free");
Greg Kroah-Hartman197b12d2007-12-20 08:13:05 -0800859 kobject_put(&ls->ls_kobj);
David Teigland79d72b52007-05-18 09:02:20 -0500860 /* The ls structure will be freed when the kobject is done with */
David Teiglande7fd4172006-01-18 09:30:29 +0000861
David Teiglande7fd4172006-01-18 09:30:29 +0000862 module_put(THIS_MODULE);
863 return 0;
864}
865
866/*
867 * Called when a system has released all its locks and is not going to use the
868 * lockspace any longer. We free everything we're managing for this lockspace.
869 * Remaining nodes will go through the recovery process as if we'd died. The
870 * lockspace must continue to function as usual, participating in recoveries,
871 * until this returns.
872 *
873 * Force has 4 possible values:
874 * 0 - don't destroy locksapce if it has any LKBs
875 * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
876 * 2 - destroy lockspace regardless of LKBs
877 * 3 - destroy lockspace as part of a forced shutdown
878 */
879
880int dlm_release_lockspace(void *lockspace, int force)
881{
882 struct dlm_ls *ls;
David Teigland0f8e0d92008-08-06 13:30:24 -0500883 int error;
David Teiglande7fd4172006-01-18 09:30:29 +0000884
885 ls = dlm_find_lockspace_local(lockspace);
886 if (!ls)
887 return -EINVAL;
888 dlm_put_lockspace(ls);
David Teigland0f8e0d92008-08-06 13:30:24 -0500889
890 mutex_lock(&ls_lock);
891 error = release_lockspace(ls, force);
892 if (!error)
893 ls_count--;
David Teigland278afcb2008-11-13 13:22:34 -0600894 if (!ls_count)
David Teigland0f8e0d92008-08-06 13:30:24 -0500895 threads_stop();
896 mutex_unlock(&ls_lock);
897
898 return error;
David Teiglande7fd4172006-01-18 09:30:29 +0000899}
900
David Teiglanddc68c7e2008-08-18 11:43:30 -0500901void dlm_stop_lockspaces(void)
902{
903 struct dlm_ls *ls;
David Teigland696b3d82013-06-25 12:48:01 -0500904 int count;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500905
906 restart:
David Teigland696b3d82013-06-25 12:48:01 -0500907 count = 0;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500908 spin_lock(&lslist_lock);
909 list_for_each_entry(ls, &lslist, ls_list) {
David Teigland696b3d82013-06-25 12:48:01 -0500910 if (!test_bit(LSFL_RUNNING, &ls->ls_flags)) {
911 count++;
David Teiglanddc68c7e2008-08-18 11:43:30 -0500912 continue;
David Teigland696b3d82013-06-25 12:48:01 -0500913 }
David Teiglanddc68c7e2008-08-18 11:43:30 -0500914 spin_unlock(&lslist_lock);
915 log_error(ls, "no userland control daemon, stopping lockspace");
916 dlm_ls_stop(ls);
917 goto restart;
918 }
919 spin_unlock(&lslist_lock);
David Teigland696b3d82013-06-25 12:48:01 -0500920
921 if (count)
922 log_print("dlm user daemon left %d lockspaces", count);
David Teiglanddc68c7e2008-08-18 11:43:30 -0500923}
924