Blame view

fs/dlm/lockspace.c 19.2 KB
e7fd41792   David Teigland   [DLM] The core of...
1
2
3
4
  /******************************************************************************
  *******************************************************************************
  **
  **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
60f98d183   David Teigland   dlm: add recovery...
5
  **  Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
e7fd41792   David Teigland   [DLM] The core of...
6
7
8
9
10
11
12
13
14
15
16
17
  **
  **  This copyrighted material is made available to anyone wishing to use,
  **  modify, copy, or redistribute it subject to the terms and conditions
  **  of the GNU General Public License v.2.
  **
  *******************************************************************************
  ******************************************************************************/
  
  #include "dlm_internal.h"
  #include "lockspace.h"
  #include "member.h"
  #include "recoverd.h"
e7fd41792   David Teigland   [DLM] The core of...
18
19
20
21
22
  #include "dir.h"
  #include "lowcomms.h"
  #include "config.h"
  #include "memory.h"
  #include "lock.h"
c56b39cd2   David Teigland   [DLM] PATCH 3/3 d...
23
  #include "recover.h"
2896ee37c   David Teigland   [DLM] fix add_req...
24
  #include "requestqueue.h"
0f8e0d9a3   David Teigland   dlm: allow multip...
25
  #include "user.h"
23e8e1aaa   David Teigland   dlm: use workqueu...
26
  #include "ast.h"
e7fd41792   David Teigland   [DLM] The core of...
27

e7fd41792   David Teigland   [DLM] The core of...
28
  static int			ls_count;
901359256   David Teigland   [DLM] Update DLM ...
29
  static struct mutex		ls_lock;
e7fd41792   David Teigland   [DLM] The core of...
30
31
32
33
34
35
36
37
38
  static struct list_head		lslist;
  static spinlock_t		lslist_lock;
  static struct task_struct *	scand_task;
  
  
  static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
  {
  	ssize_t ret = len;
  	int n = simple_strtol(buf, NULL, 0);
e2de7f565   Patrick Caulfield   [DLM] fix oops in...
39
40
41
  	ls = dlm_find_lockspace_local(ls->ls_local_handle);
  	if (!ls)
  		return -EINVAL;
e7fd41792   David Teigland   [DLM] The core of...
42
43
44
45
46
47
48
49
50
51
  	switch (n) {
  	case 0:
  		dlm_ls_stop(ls);
  		break;
  	case 1:
  		dlm_ls_start(ls);
  		break;
  	default:
  		ret = -EINVAL;
  	}
e2de7f565   Patrick Caulfield   [DLM] fix oops in...
52
  	dlm_put_lockspace(ls);
e7fd41792   David Teigland   [DLM] The core of...
53
54
55
56
57
58
59
60
61
62
63
64
65
  	return ret;
  }
  
  static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
  {
  	ls->ls_uevent_result = simple_strtol(buf, NULL, 0);
  	set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
  	wake_up(&ls->ls_uevent_wait);
  	return len;
  }
  
  static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
  {
a1d144c71   David Teigland   [DLM] use snprint...
66
67
  	return snprintf(buf, PAGE_SIZE, "%u
  ", ls->ls_global_id);
e7fd41792   David Teigland   [DLM] The core of...
68
69
70
71
72
73
74
  }
  
  static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
  {
  	ls->ls_global_id = simple_strtoul(buf, NULL, 0);
  	return len;
  }
c56b39cd2   David Teigland   [DLM] PATCH 3/3 d...
75
76
77
  static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf)
  {
  	uint32_t status = dlm_recover_status(ls);
a1d144c71   David Teigland   [DLM] use snprint...
78
79
  	return snprintf(buf, PAGE_SIZE, "%x
  ", status);
c56b39cd2   David Teigland   [DLM] PATCH 3/3 d...
80
  }
faa0f2677   David Teigland   [DLM] show nodeid...
81
82
  static ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf)
  {
a1d144c71   David Teigland   [DLM] use snprint...
83
84
  	return snprintf(buf, PAGE_SIZE, "%d
  ", ls->ls_recover_nodeid);
faa0f2677   David Teigland   [DLM] show nodeid...
85
  }
e7fd41792   David Teigland   [DLM] The core of...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  struct dlm_attr {
  	struct attribute attr;
  	ssize_t (*show)(struct dlm_ls *, char *);
  	ssize_t (*store)(struct dlm_ls *, const char *, size_t);
  };
  
  static struct dlm_attr dlm_attr_control = {
  	.attr  = {.name = "control", .mode = S_IWUSR},
  	.store = dlm_control_store
  };
  
  static struct dlm_attr dlm_attr_event = {
  	.attr  = {.name = "event_done", .mode = S_IWUSR},
  	.store = dlm_event_store
  };
  
  static struct dlm_attr dlm_attr_id = {
  	.attr  = {.name = "id", .mode = S_IRUGO | S_IWUSR},
  	.show  = dlm_id_show,
  	.store = dlm_id_store
  };
c56b39cd2   David Teigland   [DLM] PATCH 3/3 d...
107
108
109
110
  static struct dlm_attr dlm_attr_recover_status = {
  	.attr  = {.name = "recover_status", .mode = S_IRUGO},
  	.show  = dlm_recover_status_show
  };
faa0f2677   David Teigland   [DLM] show nodeid...
111
112
113
114
  static struct dlm_attr dlm_attr_recover_nodeid = {
  	.attr  = {.name = "recover_nodeid", .mode = S_IRUGO},
  	.show  = dlm_recover_nodeid_show
  };
e7fd41792   David Teigland   [DLM] The core of...
115
116
117
118
  static struct attribute *dlm_attrs[] = {
  	&dlm_attr_control.attr,
  	&dlm_attr_event.attr,
  	&dlm_attr_id.attr,
c56b39cd2   David Teigland   [DLM] PATCH 3/3 d...
119
  	&dlm_attr_recover_status.attr,
faa0f2677   David Teigland   [DLM] show nodeid...
120
  	&dlm_attr_recover_nodeid.attr,
e7fd41792   David Teigland   [DLM] The core of...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  	NULL,
  };
  
  static ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr,
  			     char *buf)
  {
  	struct dlm_ls *ls  = container_of(kobj, struct dlm_ls, ls_kobj);
  	struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
  	return a->show ? a->show(ls, buf) : 0;
  }
  
  static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
  			      const char *buf, size_t len)
  {
  	struct dlm_ls *ls  = container_of(kobj, struct dlm_ls, ls_kobj);
  	struct dlm_attr *a = container_of(attr, struct dlm_attr, attr);
  	return a->store ? a->store(ls, buf, len) : len;
  }
ba542e3b9   Patrick Caulfield   [DLM] Fix kref_pu...
139
140
141
142
143
  static void lockspace_kobj_release(struct kobject *k)
  {
  	struct dlm_ls *ls  = container_of(k, struct dlm_ls, ls_kobj);
  	kfree(ls);
  }
52cf25d0a   Emese Revfy   Driver core: Cons...
144
  static const struct sysfs_ops dlm_attr_ops = {
e7fd41792   David Teigland   [DLM] The core of...
145
146
147
148
149
150
151
  	.show  = dlm_attr_show,
  	.store = dlm_attr_store,
  };
  
  static struct kobj_type dlm_ktype = {
  	.default_attrs = dlm_attrs,
  	.sysfs_ops     = &dlm_attr_ops,
ba542e3b9   Patrick Caulfield   [DLM] Fix kref_pu...
152
  	.release       = lockspace_kobj_release,
e7fd41792   David Teigland   [DLM] The core of...
153
  };
d405936b3   Greg Kroah-Hartman   kset: convert dlm...
154
  static struct kset *dlm_kset;
e7fd41792   David Teigland   [DLM] The core of...
155

e7fd41792   David Teigland   [DLM] The core of...
156
157
158
159
160
161
162
163
  static int do_uevent(struct dlm_ls *ls, int in)
  {
  	int error;
  
  	if (in)
  		kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE);
  	else
  		kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
8b0e7b2cf   David Teigland   [DLM] wait for co...
164
165
166
167
  	log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
  
  	/* dlm_controld will see the uevent, do the necessary group management
  	   and then write to sysfs to wake us */
e7fd41792   David Teigland   [DLM] The core of...
168
169
  	error = wait_event_interruptible(ls->ls_uevent_wait,
  			test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
8b0e7b2cf   David Teigland   [DLM] wait for co...
170
171
  
  	log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
e7fd41792   David Teigland   [DLM] The core of...
172
173
174
175
176
  	if (error)
  		goto out;
  
  	error = ls->ls_uevent_result;
   out:
8b0e7b2cf   David Teigland   [DLM] wait for co...
177
178
179
  	if (error)
  		log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
  			  error, ls->ls_uevent_result);
e7fd41792   David Teigland   [DLM] The core of...
180
181
  	return error;
  }
b4a5d4bc3   Steven Whitehouse   dlm: Send lockspa...
182
183
184
185
186
187
188
189
190
191
192
193
  static int dlm_uevent(struct kset *kset, struct kobject *kobj,
  		      struct kobj_uevent_env *env)
  {
  	struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
  
  	add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
  	return 0;
  }
  
  static struct kset_uevent_ops dlm_uevent_ops = {
  	.uevent = dlm_uevent,
  };
e7fd41792   David Teigland   [DLM] The core of...
194

30727174b   Denis Cheng   dlm: add __init a...
195
  int __init dlm_lockspace_init(void)
e7fd41792   David Teigland   [DLM] The core of...
196
  {
e7fd41792   David Teigland   [DLM] The core of...
197
  	ls_count = 0;
901359256   David Teigland   [DLM] Update DLM ...
198
  	mutex_init(&ls_lock);
e7fd41792   David Teigland   [DLM] The core of...
199
200
  	INIT_LIST_HEAD(&lslist);
  	spin_lock_init(&lslist_lock);
b4a5d4bc3   Steven Whitehouse   dlm: Send lockspa...
201
  	dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
d405936b3   Greg Kroah-Hartman   kset: convert dlm...
202
  	if (!dlm_kset) {
8e24eea72   Harvey Harrison   fs: replace remai...
203
204
  		printk(KERN_WARNING "%s: can not create kset
  ", __func__);
d405936b3   Greg Kroah-Hartman   kset: convert dlm...
205
206
207
  		return -ENOMEM;
  	}
  	return 0;
e7fd41792   David Teigland   [DLM] The core of...
208
209
210
211
  }
  
  void dlm_lockspace_exit(void)
  {
d405936b3   Greg Kroah-Hartman   kset: convert dlm...
212
  	kset_unregister(dlm_kset);
e7fd41792   David Teigland   [DLM] The core of...
213
  }
c1dcf65ff   David Teigland   dlm: fix locking ...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  static struct dlm_ls *find_ls_to_scan(void)
  {
  	struct dlm_ls *ls;
  
  	spin_lock(&lslist_lock);
  	list_for_each_entry(ls, &lslist, ls_list) {
  		if (time_after_eq(jiffies, ls->ls_scan_time +
  					    dlm_config.ci_scan_secs * HZ)) {
  			spin_unlock(&lslist_lock);
  			return ls;
  		}
  	}
  	spin_unlock(&lslist_lock);
  	return NULL;
  }
e7fd41792   David Teigland   [DLM] The core of...
229
230
231
232
233
  static int dlm_scand(void *data)
  {
  	struct dlm_ls *ls;
  
  	while (!kthread_should_stop()) {
c1dcf65ff   David Teigland   dlm: fix locking ...
234
235
  		ls = find_ls_to_scan();
  		if (ls) {
85e86edf9   David Teigland   [DLM] block scand...
236
  			if (dlm_lock_recovery_try(ls)) {
c1dcf65ff   David Teigland   dlm: fix locking ...
237
  				ls->ls_scan_time = jiffies;
85e86edf9   David Teigland   [DLM] block scand...
238
  				dlm_scan_rsbs(ls);
3ae1acf93   David Teigland   [DLM] add lock ti...
239
  				dlm_scan_timeout(ls);
c6ff669ba   David Teigland   dlm: delayed repl...
240
  				dlm_scan_waiters(ls);
85e86edf9   David Teigland   [DLM] block scand...
241
  				dlm_unlock_recovery(ls);
c1dcf65ff   David Teigland   dlm: fix locking ...
242
243
  			} else {
  				ls->ls_scan_time += HZ;
85e86edf9   David Teigland   [DLM] block scand...
244
  			}
c6ff669ba   David Teigland   dlm: delayed repl...
245
  			continue;
85e86edf9   David Teigland   [DLM] block scand...
246
  		}
c6ff669ba   David Teigland   dlm: delayed repl...
247
  		schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
e7fd41792   David Teigland   [DLM] The core of...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  	}
  	return 0;
  }
  
  static int dlm_scand_start(void)
  {
  	struct task_struct *p;
  	int error = 0;
  
  	p = kthread_run(dlm_scand, NULL, "dlm_scand");
  	if (IS_ERR(p))
  		error = PTR_ERR(p);
  	else
  		scand_task = p;
  	return error;
  }
  
  static void dlm_scand_stop(void)
  {
  	kthread_stop(scand_task);
  }
e7fd41792   David Teigland   [DLM] The core of...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  struct dlm_ls *dlm_find_lockspace_global(uint32_t id)
  {
  	struct dlm_ls *ls;
  
  	spin_lock(&lslist_lock);
  
  	list_for_each_entry(ls, &lslist, ls_list) {
  		if (ls->ls_global_id == id) {
  			ls->ls_count++;
  			goto out;
  		}
  	}
  	ls = NULL;
   out:
  	spin_unlock(&lslist_lock);
  	return ls;
  }
597d0cae0   David Teigland   [DLM] dlm: user l...
286
  struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace)
e7fd41792   David Teigland   [DLM] The core of...
287
  {
597d0cae0   David Teigland   [DLM] dlm: user l...
288
  	struct dlm_ls *ls;
e7fd41792   David Teigland   [DLM] The core of...
289
290
  
  	spin_lock(&lslist_lock);
597d0cae0   David Teigland   [DLM] dlm: user l...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  	list_for_each_entry(ls, &lslist, ls_list) {
  		if (ls->ls_local_handle == lockspace) {
  			ls->ls_count++;
  			goto out;
  		}
  	}
  	ls = NULL;
   out:
  	spin_unlock(&lslist_lock);
  	return ls;
  }
  
  struct dlm_ls *dlm_find_lockspace_device(int minor)
  {
  	struct dlm_ls *ls;
  
  	spin_lock(&lslist_lock);
  	list_for_each_entry(ls, &lslist, ls_list) {
  		if (ls->ls_device.minor == minor) {
  			ls->ls_count++;
  			goto out;
  		}
  	}
  	ls = NULL;
   out:
e7fd41792   David Teigland   [DLM] The core of...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  	spin_unlock(&lslist_lock);
  	return ls;
  }
  
  void dlm_put_lockspace(struct dlm_ls *ls)
  {
  	spin_lock(&lslist_lock);
  	ls->ls_count--;
  	spin_unlock(&lslist_lock);
  }
  
  static void remove_lockspace(struct dlm_ls *ls)
  {
  	for (;;) {
  		spin_lock(&lslist_lock);
  		if (ls->ls_count == 0) {
0f8e0d9a3   David Teigland   dlm: allow multip...
332
  			WARN_ON(ls->ls_create_count != 0);
e7fd41792   David Teigland   [DLM] The core of...
333
334
335
336
337
338
339
340
341
342
343
344
  			list_del(&ls->ls_list);
  			spin_unlock(&lslist_lock);
  			return;
  		}
  		spin_unlock(&lslist_lock);
  		ssleep(1);
  	}
  }
  
  static int threads_start(void)
  {
  	int error;
e7fd41792   David Teigland   [DLM] The core of...
345
346
347
  	error = dlm_scand_start();
  	if (error) {
  		log_print("cannot start dlm_scand thread %d", error);
23e8e1aaa   David Teigland   dlm: use workqueu...
348
  		goto fail;
e7fd41792   David Teigland   [DLM] The core of...
349
350
351
352
353
354
355
356
357
358
359
360
361
  	}
  
  	/* Thread for sending/receiving messages for all lockspace's */
  	error = dlm_lowcomms_start();
  	if (error) {
  		log_print("cannot start dlm lowcomms %d", error);
  		goto scand_fail;
  	}
  
  	return 0;
  
   scand_fail:
  	dlm_scand_stop();
e7fd41792   David Teigland   [DLM] The core of...
362
363
364
365
366
367
368
369
   fail:
  	return error;
  }
  
  static void threads_stop(void)
  {
  	dlm_scand_stop();
  	dlm_lowcomms_stop();
e7fd41792   David Teigland   [DLM] The core of...
370
  }
60f98d183   David Teigland   dlm: add recovery...
371
372
373
374
  static int new_lockspace(const char *name, const char *cluster,
  			 uint32_t flags, int lvblen,
  			 const struct dlm_lockspace_ops *ops, void *ops_arg,
  			 int *ops_result, dlm_lockspace_t **lockspace)
e7fd41792   David Teigland   [DLM] The core of...
375
376
  {
  	struct dlm_ls *ls;
0f8e0d9a3   David Teigland   dlm: allow multip...
377
  	int i, size, error;
79d72b544   David Teigland   [DLM] fix new_loc...
378
  	int do_unreg = 0;
60f98d183   David Teigland   dlm: add recovery...
379
  	int namelen = strlen(name);
e7fd41792   David Teigland   [DLM] The core of...
380
381
382
383
384
385
386
387
388
  
  	if (namelen > DLM_LOCKSPACE_LEN)
  		return -EINVAL;
  
  	if (!lvblen || (lvblen % 8))
  		return -EINVAL;
  
  	if (!try_module_get(THIS_MODULE))
  		return -EINVAL;
dc68c7ed3   David Teigland   dlm: detect avail...
389
  	if (!dlm_user_daemon_available()) {
60f98d183   David Teigland   dlm: add recovery...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  		log_print("dlm user daemon not available");
  		error = -EUNATCH;
  		goto out;
  	}
  
  	if (ops && ops_result) {
  	       	if (!dlm_config.ci_recover_callbacks)
  			*ops_result = -EOPNOTSUPP;
  		else
  			*ops_result = 0;
  	}
  
  	if (dlm_config.ci_recover_callbacks && cluster &&
  	    strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) {
  		log_print("dlm cluster name %s mismatch %s",
  			  dlm_config.ci_cluster_name, cluster);
  		error = -EBADR;
  		goto out;
dc68c7ed3   David Teigland   dlm: detect avail...
408
  	}
0f8e0d9a3   David Teigland   dlm: allow multip...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
  	error = 0;
  
  	spin_lock(&lslist_lock);
  	list_for_each_entry(ls, &lslist, ls_list) {
  		WARN_ON(ls->ls_create_count <= 0);
  		if (ls->ls_namelen != namelen)
  			continue;
  		if (memcmp(ls->ls_name, name, namelen))
  			continue;
  		if (flags & DLM_LSFL_NEWEXCL) {
  			error = -EEXIST;
  			break;
  		}
  		ls->ls_create_count++;
8511a2728   David Teigland   dlm: fix use coun...
423
424
  		*lockspace = ls;
  		error = 1;
0f8e0d9a3   David Teigland   dlm: allow multip...
425
  		break;
e7fd41792   David Teigland   [DLM] The core of...
426
  	}
0f8e0d9a3   David Teigland   dlm: allow multip...
427
  	spin_unlock(&lslist_lock);
0f8e0d9a3   David Teigland   dlm: allow multip...
428
  	if (error)
8511a2728   David Teigland   dlm: fix use coun...
429
  		goto out;
0f8e0d9a3   David Teigland   dlm: allow multip...
430
431
  
  	error = -ENOMEM;
e7fd41792   David Teigland   [DLM] The core of...
432

573c24c4a   David Teigland   dlm: always use G...
433
  	ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_NOFS);
e7fd41792   David Teigland   [DLM] The core of...
434
435
  	if (!ls)
  		goto out;
e7fd41792   David Teigland   [DLM] The core of...
436
437
  	memcpy(ls->ls_name, name, namelen);
  	ls->ls_namelen = namelen;
e7fd41792   David Teigland   [DLM] The core of...
438
439
440
  	ls->ls_lvblen = lvblen;
  	ls->ls_count = 0;
  	ls->ls_flags = 0;
c1dcf65ff   David Teigland   dlm: fix locking ...
441
  	ls->ls_scan_time = jiffies;
e7fd41792   David Teigland   [DLM] The core of...
442

60f98d183   David Teigland   dlm: add recovery...
443
444
445
446
  	if (ops && dlm_config.ci_recover_callbacks) {
  		ls->ls_ops = ops;
  		ls->ls_ops_arg = ops_arg;
  	}
3ae1acf93   David Teigland   [DLM] add lock ti...
447
448
  	if (flags & DLM_LSFL_TIMEWARN)
  		set_bit(LSFL_TIMEWARN, &ls->ls_flags);
3ae1acf93   David Teigland   [DLM] add lock ti...
449

fad59c139   David Teigland   [DLM] don't requi...
450
  	/* ls_exflags are forced to match among nodes, and we don't
0f8e0d9a3   David Teigland   dlm: allow multip...
451
452
453
  	   need to require all nodes to have some flags set */
  	ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
  				    DLM_LSFL_NEWEXCL));
fad59c139   David Teigland   [DLM] don't requi...
454

68c817a1c   David Teigland   [DLM] rename dlm_...
455
  	size = dlm_config.ci_rsbtbl_size;
e7fd41792   David Teigland   [DLM] The core of...
456
  	ls->ls_rsbtbl_size = size;
c282af499   Bryn M. Reeves   dlm: use vmalloc ...
457
  	ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
e7fd41792   David Teigland   [DLM] The core of...
458
459
460
  	if (!ls->ls_rsbtbl)
  		goto out_lsfree;
  	for (i = 0; i < size; i++) {
9beb3bf5a   Bob Peterson   dlm: convert rsb ...
461
462
  		ls->ls_rsbtbl[i].keep.rb_node = NULL;
  		ls->ls_rsbtbl[i].toss.rb_node = NULL;
c7be761a8   David Teigland   dlm: change rsbtb...
463
  		spin_lock_init(&ls->ls_rsbtbl[i].lock);
e7fd41792   David Teigland   [DLM] The core of...
464
  	}
3d6aa675f   David Teigland   dlm: keep lkbs in...
465
466
  	idr_init(&ls->ls_lkbidr);
  	spin_lock_init(&ls->ls_lkbidr_spin);
e7fd41792   David Teigland   [DLM] The core of...
467

68c817a1c   David Teigland   [DLM] rename dlm_...
468
  	size = dlm_config.ci_dirtbl_size;
e7fd41792   David Teigland   [DLM] The core of...
469
  	ls->ls_dirtbl_size = size;
c282af499   Bryn M. Reeves   dlm: use vmalloc ...
470
  	ls->ls_dirtbl = vmalloc(sizeof(struct dlm_dirtable) * size);
e7fd41792   David Teigland   [DLM] The core of...
471
472
473
474
  	if (!ls->ls_dirtbl)
  		goto out_lkbfree;
  	for (i = 0; i < size; i++) {
  		INIT_LIST_HEAD(&ls->ls_dirtbl[i].list);
305a47b17   Steven Whitehouse   dlm: Change rwloc...
475
  		spin_lock_init(&ls->ls_dirtbl[i].lock);
e7fd41792   David Teigland   [DLM] The core of...
476
477
478
  	}
  
  	INIT_LIST_HEAD(&ls->ls_waiters);
901359256   David Teigland   [DLM] Update DLM ...
479
  	mutex_init(&ls->ls_waiters_mutex);
ef0c2bb05   David Teigland   [DLM] overlapping...
480
481
  	INIT_LIST_HEAD(&ls->ls_orphans);
  	mutex_init(&ls->ls_orphans_mutex);
3ae1acf93   David Teigland   [DLM] add lock ti...
482
483
  	INIT_LIST_HEAD(&ls->ls_timeout);
  	mutex_init(&ls->ls_timeout_mutex);
e7fd41792   David Teigland   [DLM] The core of...
484

3881ac04e   David Teigland   dlm: improve rsb ...
485
486
  	INIT_LIST_HEAD(&ls->ls_new_rsb);
  	spin_lock_init(&ls->ls_new_rsb_spin);
e7fd41792   David Teigland   [DLM] The core of...
487
488
489
490
491
492
493
494
495
  	INIT_LIST_HEAD(&ls->ls_nodes);
  	INIT_LIST_HEAD(&ls->ls_nodes_gone);
  	ls->ls_num_nodes = 0;
  	ls->ls_low_nodeid = 0;
  	ls->ls_total_weight = 0;
  	ls->ls_node_array = NULL;
  
  	memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
  	ls->ls_stub_rsb.res_ls = ls;
5de6319b1   David Teigland   [DLM] more info t...
496
497
  	ls->ls_debug_rsb_dentry = NULL;
  	ls->ls_debug_waiters_dentry = NULL;
e7fd41792   David Teigland   [DLM] The core of...
498
499
500
  
  	init_waitqueue_head(&ls->ls_uevent_wait);
  	ls->ls_uevent_result = 0;
8b0e7b2cf   David Teigland   [DLM] wait for co...
501
502
  	init_completion(&ls->ls_members_done);
  	ls->ls_members_result = -1;
e7fd41792   David Teigland   [DLM] The core of...
503

23e8e1aaa   David Teigland   dlm: use workqueu...
504
505
  	mutex_init(&ls->ls_cb_mutex);
  	INIT_LIST_HEAD(&ls->ls_cb_delay);
e7fd41792   David Teigland   [DLM] The core of...
506
  	ls->ls_recoverd_task = NULL;
901359256   David Teigland   [DLM] Update DLM ...
507
  	mutex_init(&ls->ls_recoverd_active);
e7fd41792   David Teigland   [DLM] The core of...
508
  	spin_lock_init(&ls->ls_recover_lock);
98f176fb3   David Teigland   [DLM] don't accep...
509
510
  	spin_lock_init(&ls->ls_rcom_spin);
  	get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
e7fd41792   David Teigland   [DLM] The core of...
511
512
513
514
  	ls->ls_recover_status = 0;
  	ls->ls_recover_seq = 0;
  	ls->ls_recover_args = NULL;
  	init_rwsem(&ls->ls_in_recovery);
c36258b59   David Teigland   [DLM] block dlm_r...
515
  	init_rwsem(&ls->ls_recv_active);
e7fd41792   David Teigland   [DLM] The core of...
516
  	INIT_LIST_HEAD(&ls->ls_requestqueue);
901359256   David Teigland   [DLM] Update DLM ...
517
  	mutex_init(&ls->ls_requestqueue_mutex);
597d0cae0   David Teigland   [DLM] dlm: user l...
518
  	mutex_init(&ls->ls_clear_proc_locks);
e7fd41792   David Teigland   [DLM] The core of...
519

573c24c4a   David Teigland   dlm: always use G...
520
  	ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
e7fd41792   David Teigland   [DLM] The core of...
521
522
  	if (!ls->ls_recover_buf)
  		goto out_dirfree;
757a42719   David Teigland   dlm: add node slo...
523
524
525
526
  	ls->ls_slot = 0;
  	ls->ls_num_slots = 0;
  	ls->ls_slots_size = 0;
  	ls->ls_slots = NULL;
e7fd41792   David Teigland   [DLM] The core of...
527
528
529
  	INIT_LIST_HEAD(&ls->ls_recover_list);
  	spin_lock_init(&ls->ls_recover_list_lock);
  	ls->ls_recover_list_count = 0;
597d0cae0   David Teigland   [DLM] dlm: user l...
530
  	ls->ls_local_handle = ls;
e7fd41792   David Teigland   [DLM] The core of...
531
532
533
534
535
  	init_waitqueue_head(&ls->ls_wait_general);
  	INIT_LIST_HEAD(&ls->ls_root_list);
  	init_rwsem(&ls->ls_root_sem);
  
  	down_write(&ls->ls_in_recovery);
5f88f1ea1   David Teigland   [DLM] add new loc...
536
  	spin_lock(&lslist_lock);
0f8e0d9a3   David Teigland   dlm: allow multip...
537
  	ls->ls_create_count = 1;
5f88f1ea1   David Teigland   [DLM] add new loc...
538
539
  	list_add(&ls->ls_list, &lslist);
  	spin_unlock(&lslist_lock);
23e8e1aaa   David Teigland   dlm: use workqueu...
540
541
542
543
544
545
546
  	if (flags & DLM_LSFL_FS) {
  		error = dlm_callback_start(ls);
  		if (error) {
  			log_error(ls, "can't start dlm_callback %d", error);
  			goto out_delist;
  		}
  	}
5f88f1ea1   David Teigland   [DLM] add new loc...
547
  	/* needs to find ls in lslist */
e7fd41792   David Teigland   [DLM] The core of...
548
549
550
  	error = dlm_recoverd_start(ls);
  	if (error) {
  		log_error(ls, "can't start dlm_recoverd %d", error);
23e8e1aaa   David Teigland   dlm: use workqueu...
551
  		goto out_callback;
e7fd41792   David Teigland   [DLM] The core of...
552
  	}
901195ed7   Greg Kroah-Hartman   Kobject: change G...
553
554
555
  	ls->ls_kobj.kset = dlm_kset;
  	error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
  				     "%s", ls->ls_name);
e7fd41792   David Teigland   [DLM] The core of...
556
  	if (error)
23e8e1aaa   David Teigland   dlm: use workqueu...
557
  		goto out_recoverd;
901195ed7   Greg Kroah-Hartman   Kobject: change G...
558
  	kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
79d72b544   David Teigland   [DLM] fix new_loc...
559
560
561
  
  	/* let kobject handle freeing of ls if there's an error */
  	do_unreg = 1;
e7fd41792   David Teigland   [DLM] The core of...
562

8b0e7b2cf   David Teigland   [DLM] wait for co...
563
564
565
566
567
  	/* This uevent triggers dlm_controld in userspace to add us to the
  	   group of nodes that are members of this lockspace (managed by the
  	   cluster infrastructure.)  Once it's done that, it tells us who the
  	   current lockspace members are (via configfs) and then tells the
  	   lockspace to start running (via sysfs) in dlm_ls_start(). */
e7fd41792   David Teigland   [DLM] The core of...
568
569
  	error = do_uevent(ls, 1);
  	if (error)
23e8e1aaa   David Teigland   dlm: use workqueu...
570
  		goto out_recoverd;
79d72b544   David Teigland   [DLM] fix new_loc...
571

8b0e7b2cf   David Teigland   [DLM] wait for co...
572
573
574
575
  	wait_for_completion(&ls->ls_members_done);
  	error = ls->ls_members_result;
  	if (error)
  		goto out_members;
79d72b544   David Teigland   [DLM] fix new_loc...
576
577
578
  	dlm_create_debug_file(ls);
  
  	log_debug(ls, "join complete");
e7fd41792   David Teigland   [DLM] The core of...
579
580
  	*lockspace = ls;
  	return 0;
8b0e7b2cf   David Teigland   [DLM] wait for co...
581
582
583
584
   out_members:
  	do_uevent(ls, 0);
  	dlm_clear_members(ls);
  	kfree(ls->ls_node_array);
23e8e1aaa   David Teigland   dlm: use workqueu...
585
   out_recoverd:
5f88f1ea1   David Teigland   [DLM] add new loc...
586
  	dlm_recoverd_stop(ls);
23e8e1aaa   David Teigland   dlm: use workqueu...
587
588
   out_callback:
  	dlm_callback_stop(ls);
79d72b544   David Teigland   [DLM] fix new_loc...
589
   out_delist:
e7fd41792   David Teigland   [DLM] The core of...
590
591
592
  	spin_lock(&lslist_lock);
  	list_del(&ls->ls_list);
  	spin_unlock(&lslist_lock);
e7fd41792   David Teigland   [DLM] The core of...
593
594
  	kfree(ls->ls_recover_buf);
   out_dirfree:
c282af499   Bryn M. Reeves   dlm: use vmalloc ...
595
  	vfree(ls->ls_dirtbl);
e7fd41792   David Teigland   [DLM] The core of...
596
   out_lkbfree:
3d6aa675f   David Teigland   dlm: keep lkbs in...
597
  	idr_destroy(&ls->ls_lkbidr);
c282af499   Bryn M. Reeves   dlm: use vmalloc ...
598
  	vfree(ls->ls_rsbtbl);
e7fd41792   David Teigland   [DLM] The core of...
599
   out_lsfree:
79d72b544   David Teigland   [DLM] fix new_loc...
600
  	if (do_unreg)
197b12d67   Greg Kroah-Hartman   Kobject: convert ...
601
  		kobject_put(&ls->ls_kobj);
79d72b544   David Teigland   [DLM] fix new_loc...
602
603
  	else
  		kfree(ls);
e7fd41792   David Teigland   [DLM] The core of...
604
605
606
607
   out:
  	module_put(THIS_MODULE);
  	return error;
  }
60f98d183   David Teigland   dlm: add recovery...
608
609
610
611
  int dlm_new_lockspace(const char *name, const char *cluster,
  		      uint32_t flags, int lvblen,
  		      const struct dlm_lockspace_ops *ops, void *ops_arg,
  		      int *ops_result, dlm_lockspace_t **lockspace)
e7fd41792   David Teigland   [DLM] The core of...
612
613
  {
  	int error = 0;
901359256   David Teigland   [DLM] Update DLM ...
614
  	mutex_lock(&ls_lock);
e7fd41792   David Teigland   [DLM] The core of...
615
616
617
618
  	if (!ls_count)
  		error = threads_start();
  	if (error)
  		goto out;
60f98d183   David Teigland   dlm: add recovery...
619
620
  	error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg,
  			      ops_result, lockspace);
e7fd41792   David Teigland   [DLM] The core of...
621
622
  	if (!error)
  		ls_count++;
8511a2728   David Teigland   dlm: fix use coun...
623
624
625
  	if (error > 0)
  		error = 0;
  	if (!ls_count)
8b0e7b2cf   David Teigland   [DLM] wait for co...
626
  		threads_stop();
e7fd41792   David Teigland   [DLM] The core of...
627
   out:
901359256   David Teigland   [DLM] Update DLM ...
628
  	mutex_unlock(&ls_lock);
e7fd41792   David Teigland   [DLM] The core of...
629
630
  	return error;
  }
3d6aa675f   David Teigland   dlm: keep lkbs in...
631
  static int lkb_idr_is_local(int id, void *p, void *data)
e7fd41792   David Teigland   [DLM] The core of...
632
  {
3d6aa675f   David Teigland   dlm: keep lkbs in...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
  	struct dlm_lkb *lkb = p;
  
  	if (!lkb->lkb_nodeid)
  		return 1;
  	return 0;
  }
  
  static int lkb_idr_is_any(int id, void *p, void *data)
  {
  	return 1;
  }
  
  static int lkb_idr_free(int id, void *p, void *data)
  {
  	struct dlm_lkb *lkb = p;
3d6aa675f   David Teigland   dlm: keep lkbs in...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
  	if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
  		dlm_free_lvb(lkb->lkb_lvbptr);
  
  	dlm_free_lkb(lkb);
  	return 0;
  }
  
  /* NOTE: We check the lkbidr here rather than the resource table.
     This is because there may be LKBs queued as ASTs that have been unlinked
     from their RSBs and are pending deletion once the AST has been delivered */
  
  static int lockspace_busy(struct dlm_ls *ls, int force)
  {
  	int rv;
  
  	spin_lock(&ls->ls_lkbidr_spin);
  	if (force == 0) {
  		rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls);
  	} else if (force == 1) {
  		rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls);
  	} else {
  		rv = 0;
e7fd41792   David Teigland   [DLM] The core of...
670
  	}
3d6aa675f   David Teigland   dlm: keep lkbs in...
671
672
  	spin_unlock(&ls->ls_lkbidr_spin);
  	return rv;
e7fd41792   David Teigland   [DLM] The core of...
673
674
675
676
  }
  
  static int release_lockspace(struct dlm_ls *ls, int force)
  {
e7fd41792   David Teigland   [DLM] The core of...
677
  	struct dlm_rsb *rsb;
9beb3bf5a   Bob Peterson   dlm: convert rsb ...
678
  	struct rb_node *n;
0f8e0d9a3   David Teigland   dlm: allow multip...
679
  	int i, busy, rv;
3d6aa675f   David Teigland   dlm: keep lkbs in...
680
  	busy = lockspace_busy(ls, force);
0f8e0d9a3   David Teigland   dlm: allow multip...
681
682
683
  
  	spin_lock(&lslist_lock);
  	if (ls->ls_create_count == 1) {
3d6aa675f   David Teigland   dlm: keep lkbs in...
684
  		if (busy) {
0f8e0d9a3   David Teigland   dlm: allow multip...
685
  			rv = -EBUSY;
3d6aa675f   David Teigland   dlm: keep lkbs in...
686
  		} else {
0f8e0d9a3   David Teigland   dlm: allow multip...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  			/* remove_lockspace takes ls off lslist */
  			ls->ls_create_count = 0;
  			rv = 0;
  		}
  	} else if (ls->ls_create_count > 1) {
  		rv = --ls->ls_create_count;
  	} else {
  		rv = -EINVAL;
  	}
  	spin_unlock(&lslist_lock);
  
  	if (rv) {
  		log_debug(ls, "release_lockspace no remove %d", rv);
  		return rv;
  	}
e7fd41792   David Teigland   [DLM] The core of...
702

0f8e0d9a3   David Teigland   dlm: allow multip...
703
  	dlm_device_deregister(ls);
e7fd41792   David Teigland   [DLM] The core of...
704

dc68c7ed3   David Teigland   dlm: detect avail...
705
  	if (force < 3 && dlm_user_daemon_available())
e7fd41792   David Teigland   [DLM] The core of...
706
707
708
  		do_uevent(ls, 0);
  
  	dlm_recoverd_stop(ls);
23e8e1aaa   David Teigland   dlm: use workqueu...
709
  	dlm_callback_stop(ls);
e7fd41792   David Teigland   [DLM] The core of...
710
711
712
  	remove_lockspace(ls);
  
  	dlm_delete_debug_file(ls);
e7fd41792   David Teigland   [DLM] The core of...
713
714
715
716
717
718
719
  	kfree(ls->ls_recover_buf);
  
  	/*
  	 * Free direntry structs.
  	 */
  
  	dlm_dir_clear(ls);
c282af499   Bryn M. Reeves   dlm: use vmalloc ...
720
  	vfree(ls->ls_dirtbl);
e7fd41792   David Teigland   [DLM] The core of...
721
722
  
  	/*
3d6aa675f   David Teigland   dlm: keep lkbs in...
723
  	 * Free all lkb's in idr
e7fd41792   David Teigland   [DLM] The core of...
724
  	 */
3d6aa675f   David Teigland   dlm: keep lkbs in...
725
726
727
  	idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls);
  	idr_remove_all(&ls->ls_lkbidr);
  	idr_destroy(&ls->ls_lkbidr);
e7fd41792   David Teigland   [DLM] The core of...
728

e7fd41792   David Teigland   [DLM] The core of...
729
730
731
732
733
  	/*
  	 * Free all rsb's on rsbtbl[] lists
  	 */
  
  	for (i = 0; i < ls->ls_rsbtbl_size; i++) {
9beb3bf5a   Bob Peterson   dlm: convert rsb ...
734
735
736
  		while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) {
  			rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
  			rb_erase(n, &ls->ls_rsbtbl[i].keep);
52bda2b5b   David Teigland   dlm: use dlm pref...
737
  			dlm_free_rsb(rsb);
e7fd41792   David Teigland   [DLM] The core of...
738
  		}
9beb3bf5a   Bob Peterson   dlm: convert rsb ...
739
740
741
  		while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) {
  			rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
  			rb_erase(n, &ls->ls_rsbtbl[i].toss);
52bda2b5b   David Teigland   dlm: use dlm pref...
742
  			dlm_free_rsb(rsb);
e7fd41792   David Teigland   [DLM] The core of...
743
744
  		}
  	}
c282af499   Bryn M. Reeves   dlm: use vmalloc ...
745
  	vfree(ls->ls_rsbtbl);
e7fd41792   David Teigland   [DLM] The core of...
746

3881ac04e   David Teigland   dlm: improve rsb ...
747
748
749
750
751
752
  	while (!list_empty(&ls->ls_new_rsb)) {
  		rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
  				       res_hashchain);
  		list_del(&rsb->res_hashchain);
  		dlm_free_rsb(rsb);
  	}
e7fd41792   David Teigland   [DLM] The core of...
753
754
755
  	/*
  	 * Free structures on any other lists
  	 */
2896ee37c   David Teigland   [DLM] fix add_req...
756
  	dlm_purge_requestqueue(ls);
e7fd41792   David Teigland   [DLM] The core of...
757
758
759
760
761
  	kfree(ls->ls_recover_args);
  	dlm_clear_free_entries(ls);
  	dlm_clear_members(ls);
  	dlm_clear_members_gone(ls);
  	kfree(ls->ls_node_array);
0f8e0d9a3   David Teigland   dlm: allow multip...
762
  	log_debug(ls, "release_lockspace final free");
197b12d67   Greg Kroah-Hartman   Kobject: convert ...
763
  	kobject_put(&ls->ls_kobj);
79d72b544   David Teigland   [DLM] fix new_loc...
764
  	/* The ls structure will be freed when the kobject is done with */
e7fd41792   David Teigland   [DLM] The core of...
765

e7fd41792   David Teigland   [DLM] The core of...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
  	module_put(THIS_MODULE);
  	return 0;
  }
  
  /*
   * Called when a system has released all its locks and is not going to use the
   * lockspace any longer.  We free everything we're managing for this lockspace.
   * Remaining nodes will go through the recovery process as if we'd died.  The
   * lockspace must continue to function as usual, participating in recoveries,
   * until this returns.
   *
   * Force has 4 possible values:
   * 0 - don't destroy locksapce if it has any LKBs
   * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
   * 2 - destroy lockspace regardless of LKBs
   * 3 - destroy lockspace as part of a forced shutdown
   */
  
  int dlm_release_lockspace(void *lockspace, int force)
  {
  	struct dlm_ls *ls;
0f8e0d9a3   David Teigland   dlm: allow multip...
787
  	int error;
e7fd41792   David Teigland   [DLM] The core of...
788
789
790
791
792
  
  	ls = dlm_find_lockspace_local(lockspace);
  	if (!ls)
  		return -EINVAL;
  	dlm_put_lockspace(ls);
0f8e0d9a3   David Teigland   dlm: allow multip...
793
794
795
796
797
  
  	mutex_lock(&ls_lock);
  	error = release_lockspace(ls, force);
  	if (!error)
  		ls_count--;
278afcbf4   David Teigland   dlm: fix shutdown...
798
  	if (!ls_count)
0f8e0d9a3   David Teigland   dlm: allow multip...
799
800
801
802
  		threads_stop();
  	mutex_unlock(&ls_lock);
  
  	return error;
e7fd41792   David Teigland   [DLM] The core of...
803
  }
dc68c7ed3   David Teigland   dlm: detect avail...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
  void dlm_stop_lockspaces(void)
  {
  	struct dlm_ls *ls;
  
   restart:
  	spin_lock(&lslist_lock);
  	list_for_each_entry(ls, &lslist, ls_list) {
  		if (!test_bit(LSFL_RUNNING, &ls->ls_flags))
  			continue;
  		spin_unlock(&lslist_lock);
  		log_error(ls, "no userland control daemon, stopping lockspace");
  		dlm_ls_stop(ls);
  		goto restart;
  	}
  	spin_unlock(&lslist_lock);
  }