aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/locking/dlm/lock.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2006-01-16 11:52:38 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-01-16 11:52:38 -0500
commit29b7998d887529eca1ef43c8ca7b278448dc983c (patch)
tree8968045a976eba9ce349b045c8db7a9ee82a6a2e /fs/gfs2/locking/dlm/lock.c
parentb3b94faa5fe5968827ba0640ee9fba4b3e7f736e (diff)
[GFS2] The lock modules for GFS2
This patch contains the pluggable locking modules for GFS2. Signed-off-by: David Teigland <teigland@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/locking/dlm/lock.c')
-rw-r--r--fs/gfs2/locking/dlm/lock.c537
1 files changed, 537 insertions, 0 deletions
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
new file mode 100644
index 000000000000..daf59d504e29
--- /dev/null
+++ b/fs/gfs2/locking/dlm/lock.c
@@ -0,0 +1,537 @@
1/******************************************************************************
2*******************************************************************************
3**
4** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
6**
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 "lock_dlm.h"
15
16static char junk_lvb[GDLM_LVB_SIZE];
17
18static void queue_complete(struct gdlm_lock *lp)
19{
20 struct gdlm_ls *ls = lp->ls;
21
22 clear_bit(LFL_ACTIVE, &lp->flags);
23
24 spin_lock(&ls->async_lock);
25 list_add_tail(&lp->clist, &ls->complete);
26 spin_unlock(&ls->async_lock);
27 wake_up(&ls->thread_wait);
28}
29
30static inline void gdlm_ast(void *astarg)
31{
32 queue_complete((struct gdlm_lock *) astarg);
33}
34
35static inline void gdlm_bast(void *astarg, int mode)
36{
37 struct gdlm_lock *lp = astarg;
38 struct gdlm_ls *ls = lp->ls;
39
40 if (!mode) {
41 printk("lock_dlm: bast mode zero %x,%"PRIx64"\n",
42 lp->lockname.ln_type, lp->lockname.ln_number);
43 return;
44 }
45
46 spin_lock(&ls->async_lock);
47 if (!lp->bast_mode) {
48 list_add_tail(&lp->blist, &ls->blocking);
49 lp->bast_mode = mode;
50 } else if (lp->bast_mode < mode)
51 lp->bast_mode = mode;
52 spin_unlock(&ls->async_lock);
53 wake_up(&ls->thread_wait);
54}
55
56void gdlm_queue_delayed(struct gdlm_lock *lp)
57{
58 struct gdlm_ls *ls = lp->ls;
59
60 spin_lock(&ls->async_lock);
61 list_add_tail(&lp->delay_list, &ls->delayed);
62 spin_unlock(&ls->async_lock);
63}
64
65/* convert gfs lock-state to dlm lock-mode */
66
67static int16_t make_mode(int16_t lmstate)
68{
69 switch (lmstate) {
70 case LM_ST_UNLOCKED:
71 return DLM_LOCK_NL;
72 case LM_ST_EXCLUSIVE:
73 return DLM_LOCK_EX;
74 case LM_ST_DEFERRED:
75 return DLM_LOCK_CW;
76 case LM_ST_SHARED:
77 return DLM_LOCK_PR;
78 default:
79 GDLM_ASSERT(0, printk("unknown LM state %d\n", lmstate););
80 }
81}
82
83/* convert dlm lock-mode to gfs lock-state */
84
85int16_t gdlm_make_lmstate(int16_t dlmmode)
86{
87 switch (dlmmode) {
88 case DLM_LOCK_IV:
89 case DLM_LOCK_NL:
90 return LM_ST_UNLOCKED;
91 case DLM_LOCK_EX:
92 return LM_ST_EXCLUSIVE;
93 case DLM_LOCK_CW:
94 return LM_ST_DEFERRED;
95 case DLM_LOCK_PR:
96 return LM_ST_SHARED;
97 default:
98 GDLM_ASSERT(0, printk("unknown DLM mode %d\n", dlmmode););
99 }
100}
101
102/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and
103 DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */
104
105static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state)
106{
107 int16_t cur = make_mode(cur_state);
108 if (lp->cur != DLM_LOCK_IV)
109 GDLM_ASSERT(lp->cur == cur, printk("%d, %d\n", lp->cur, cur););
110}
111
112static inline unsigned int make_flags(struct gdlm_lock *lp,
113 unsigned int gfs_flags,
114 int16_t cur, int16_t req)
115{
116 unsigned int lkf = 0;
117
118 if (gfs_flags & LM_FLAG_TRY)
119 lkf |= DLM_LKF_NOQUEUE;
120
121 if (gfs_flags & LM_FLAG_TRY_1CB) {
122 lkf |= DLM_LKF_NOQUEUE;
123 lkf |= DLM_LKF_NOQUEUEBAST;
124 }
125
126 if (gfs_flags & LM_FLAG_PRIORITY) {
127 lkf |= DLM_LKF_NOORDER;
128 lkf |= DLM_LKF_HEADQUE;
129 }
130
131 if (gfs_flags & LM_FLAG_ANY) {
132 if (req == DLM_LOCK_PR)
133 lkf |= DLM_LKF_ALTCW;
134 else if (req == DLM_LOCK_CW)
135 lkf |= DLM_LKF_ALTPR;
136 }
137
138 if (lp->lksb.sb_lkid != 0) {
139 lkf |= DLM_LKF_CONVERT;
140
141 /* Conversion deadlock avoidance by DLM */
142
143 if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
144 !(lkf & DLM_LKF_NOQUEUE) &&
145 cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
146 lkf |= DLM_LKF_CONVDEADLK;
147 }
148
149 if (lp->lvb)
150 lkf |= DLM_LKF_VALBLK;
151
152 return lkf;
153}
154
155/* make_strname - convert GFS lock numbers to a string */
156
157static inline void make_strname(struct lm_lockname *lockname,
158 struct gdlm_strname *str)
159{
160 sprintf(str->name, "%8x%16"PRIx64, lockname->ln_type,
161 lockname->ln_number);
162 str->namelen = GDLM_STRNAME_BYTES;
163}
164
165int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
166 struct gdlm_lock **lpp)
167{
168 struct gdlm_lock *lp;
169
170 lp = kmalloc(sizeof(struct gdlm_lock), GFP_KERNEL);
171 if (!lp)
172 return -ENOMEM;
173
174 memset(lp, 0, sizeof(struct gdlm_lock));
175 lp->lockname = *name;
176 lp->ls = ls;
177 lp->cur = DLM_LOCK_IV;
178 lp->lvb = NULL;
179 lp->hold_null = NULL;
180 init_completion(&lp->ast_wait);
181 INIT_LIST_HEAD(&lp->clist);
182 INIT_LIST_HEAD(&lp->blist);
183 INIT_LIST_HEAD(&lp->delay_list);
184
185 spin_lock(&ls->async_lock);
186 list_add(&lp->all_list, &ls->all_locks);
187 ls->all_locks_count++;
188 spin_unlock(&ls->async_lock);
189
190 *lpp = lp;
191 return 0;
192}
193
194void gdlm_delete_lp(struct gdlm_lock *lp)
195{
196 struct gdlm_ls *ls = lp->ls;
197
198 spin_lock(&ls->async_lock);
199 if (!list_empty(&lp->clist))
200 list_del_init(&lp->clist);
201 if (!list_empty(&lp->blist))
202 list_del_init(&lp->blist);
203 if (!list_empty(&lp->delay_list))
204 list_del_init(&lp->delay_list);
205 GDLM_ASSERT(!list_empty(&lp->all_list),);
206 list_del_init(&lp->all_list);
207 ls->all_locks_count--;
208 spin_unlock(&ls->async_lock);
209
210 kfree(lp);
211}
212
213int gdlm_get_lock(lm_lockspace_t *lockspace, struct lm_lockname *name,
214 lm_lock_t **lockp)
215{
216 struct gdlm_lock *lp;
217 int error;
218
219 error = gdlm_create_lp((struct gdlm_ls *) lockspace, name, &lp);
220
221 *lockp = (lm_lock_t *) lp;
222 return error;
223}
224
225void gdlm_put_lock(lm_lock_t *lock)
226{
227 gdlm_delete_lp((struct gdlm_lock *) lock);
228}
229
230void gdlm_do_lock(struct gdlm_lock *lp, struct dlm_range *range)
231{
232 struct gdlm_ls *ls = lp->ls;
233 struct gdlm_strname str;
234 int error, bast = 1;
235
236 /*
237 * When recovery is in progress, delay lock requests for submission
238 * once recovery is done. Requests for recovery (NOEXP) and unlocks
239 * can pass.
240 */
241
242 if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
243 !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) {
244 gdlm_queue_delayed(lp);
245 return;
246 }
247
248 /*
249 * Submit the actual lock request.
250 */
251
252 if (test_bit(LFL_NOBAST, &lp->flags))
253 bast = 0;
254
255 make_strname(&lp->lockname, &str);
256
257 set_bit(LFL_ACTIVE, &lp->flags);
258
259 log_debug("lk %x,%"PRIx64" id %x %d,%d %x", lp->lockname.ln_type,
260 lp->lockname.ln_number, lp->lksb.sb_lkid,
261 lp->cur, lp->req, lp->lkf);
262
263 error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf,
264 str.name, str.namelen, 0, gdlm_ast, (void *) lp,
265 bast ? gdlm_bast : NULL, range);
266
267 if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) {
268 lp->lksb.sb_status = -EAGAIN;
269 queue_complete(lp);
270 error = 0;
271 }
272
273 GDLM_ASSERT(!error,
274 printk("%s: num=%x,%"PRIx64" err=%d cur=%d req=%d lkf=%x\n",
275 ls->fsname, lp->lockname.ln_type,
276 lp->lockname.ln_number, error, lp->cur, lp->req,
277 lp->lkf););
278}
279
280void gdlm_do_unlock(struct gdlm_lock *lp)
281{
282 unsigned int lkf = 0;
283 int error;
284
285 set_bit(LFL_DLM_UNLOCK, &lp->flags);
286 set_bit(LFL_ACTIVE, &lp->flags);
287
288 if (lp->lvb)
289 lkf = DLM_LKF_VALBLK;
290
291 log_debug("un %x,%"PRIx64" %x %d %x", lp->lockname.ln_type,
292 lp->lockname.ln_number, lp->lksb.sb_lkid, lp->cur, lkf);
293
294 error = dlm_unlock(lp->ls->dlm_lockspace, lp->lksb.sb_lkid, lkf,
295 NULL, lp);
296
297 GDLM_ASSERT(!error,
298 printk("%s: error=%d num=%x,%"PRIx64" lkf=%x flags=%lx\n",
299 lp->ls->fsname, error, lp->lockname.ln_type,
300 lp->lockname.ln_number, lkf, lp->flags););
301}
302
303unsigned int gdlm_lock(lm_lock_t *lock, unsigned int cur_state,
304 unsigned int req_state, unsigned int flags)
305{
306 struct gdlm_lock *lp = (struct gdlm_lock *) lock;
307
308 clear_bit(LFL_DLM_CANCEL, &lp->flags);
309 if (flags & LM_FLAG_NOEXP)
310 set_bit(LFL_NOBLOCK, &lp->flags);
311
312 check_cur_state(lp, cur_state);
313 lp->req = make_mode(req_state);
314 lp->lkf = make_flags(lp, flags, lp->cur, lp->req);
315
316 gdlm_do_lock(lp, NULL);
317 return LM_OUT_ASYNC;
318}
319
320unsigned int gdlm_unlock(lm_lock_t *lock, unsigned int cur_state)
321{
322 struct gdlm_lock *lp = (struct gdlm_lock *) lock;
323
324 clear_bit(LFL_DLM_CANCEL, &lp->flags);
325 if (lp->cur == DLM_LOCK_IV)
326 return 0;
327 gdlm_do_unlock(lp);
328 return LM_OUT_ASYNC;
329}
330
331void gdlm_cancel(lm_lock_t *lock)
332{
333 struct gdlm_lock *lp = (struct gdlm_lock *) lock;
334 struct gdlm_ls *ls = lp->ls;
335 int error, delay_list = 0;
336
337 if (test_bit(LFL_DLM_CANCEL, &lp->flags))
338 return;
339
340 log_all("gdlm_cancel %x,%"PRIx64" flags %lx",
341 lp->lockname.ln_type, lp->lockname.ln_number, lp->flags);
342
343 spin_lock(&ls->async_lock);
344 if (!list_empty(&lp->delay_list)) {
345 list_del_init(&lp->delay_list);
346 delay_list = 1;
347 }
348 spin_unlock(&ls->async_lock);
349
350 if (delay_list) {
351 set_bit(LFL_CANCEL, &lp->flags);
352 set_bit(LFL_ACTIVE, &lp->flags);
353 queue_complete(lp);
354 return;
355 }
356
357 if (!test_bit(LFL_ACTIVE, &lp->flags) ||
358 test_bit(LFL_DLM_UNLOCK, &lp->flags)) {
359 log_all("gdlm_cancel skip %x,%"PRIx64" flags %lx",
360 lp->lockname.ln_type, lp->lockname.ln_number,
361 lp->flags);
362 return;
363 }
364
365 /* the lock is blocked in the dlm */
366
367 set_bit(LFL_DLM_CANCEL, &lp->flags);
368 set_bit(LFL_ACTIVE, &lp->flags);
369
370 error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL,
371 NULL, lp);
372
373 log_all("gdlm_cancel rv %d %x,%"PRIx64" flags %lx", error,
374 lp->lockname.ln_type, lp->lockname.ln_number, lp->flags);
375
376 if (error == -EBUSY)
377 clear_bit(LFL_DLM_CANCEL, &lp->flags);
378}
379
380int gdlm_add_lvb(struct gdlm_lock *lp)
381{
382 char *lvb;
383
384 lvb = kmalloc(GDLM_LVB_SIZE, GFP_KERNEL);
385 if (!lvb)
386 return -ENOMEM;
387
388 memset(lvb, 0, GDLM_LVB_SIZE);
389
390 lp->lksb.sb_lvbptr = lvb;
391 lp->lvb = lvb;
392 return 0;
393}
394
395void gdlm_del_lvb(struct gdlm_lock *lp)
396{
397 kfree(lp->lvb);
398 lp->lvb = NULL;
399 lp->lksb.sb_lvbptr = NULL;
400}
401
402/* This can do a synchronous dlm request (requiring a lock_dlm thread to get
403 the completion) because gfs won't call hold_lvb() during a callback (from
404 the context of a lock_dlm thread). */
405
406static int hold_null_lock(struct gdlm_lock *lp)
407{
408 struct gdlm_lock *lpn = NULL;
409 int error;
410
411 if (lp->hold_null) {
412 printk("lock_dlm: lvb already held\n");
413 return 0;
414 }
415
416 error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn);
417 if (error)
418 goto out;
419
420 lpn->lksb.sb_lvbptr = junk_lvb;
421 lpn->lvb = junk_lvb;
422
423 lpn->req = DLM_LOCK_NL;
424 lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
425 set_bit(LFL_NOBAST, &lpn->flags);
426 set_bit(LFL_INLOCK, &lpn->flags);
427
428 init_completion(&lpn->ast_wait);
429 gdlm_do_lock(lpn, NULL);
430 wait_for_completion(&lpn->ast_wait);
431 error = lp->lksb.sb_status;
432 if (error) {
433 printk("lock_dlm: hold_null_lock dlm error %d\n", error);
434 gdlm_delete_lp(lpn);
435 lpn = NULL;
436 }
437 out:
438 lp->hold_null = lpn;
439 return error;
440}
441
442/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get
443 the completion) because gfs may call unhold_lvb() during a callback (from
444 the context of a lock_dlm thread) which could cause a deadlock since the
445 other lock_dlm thread could be engaged in recovery. */
446
447static void unhold_null_lock(struct gdlm_lock *lp)
448{
449 struct gdlm_lock *lpn = lp->hold_null;
450
451 GDLM_ASSERT(lpn,);
452 lpn->lksb.sb_lvbptr = NULL;
453 lpn->lvb = NULL;
454 set_bit(LFL_UNLOCK_DELETE, &lpn->flags);
455 gdlm_do_unlock(lpn);
456 lp->hold_null = NULL;
457}
458
459/* Acquire a NL lock because gfs requires the value block to remain
460 intact on the resource while the lvb is "held" even if it's holding no locks
461 on the resource. */
462
463int gdlm_hold_lvb(lm_lock_t *lock, char **lvbp)
464{
465 struct gdlm_lock *lp = (struct gdlm_lock *) lock;
466 int error;
467
468 error = gdlm_add_lvb(lp);
469 if (error)
470 return error;
471
472 *lvbp = lp->lvb;
473
474 error = hold_null_lock(lp);
475 if (error)
476 gdlm_del_lvb(lp);
477
478 return error;
479}
480
481void gdlm_unhold_lvb(lm_lock_t *lock, char *lvb)
482{
483 struct gdlm_lock *lp = (struct gdlm_lock *) lock;
484
485 unhold_null_lock(lp);
486 gdlm_del_lvb(lp);
487}
488
489void gdlm_sync_lvb(lm_lock_t *lock, char *lvb)
490{
491 struct gdlm_lock *lp = (struct gdlm_lock *) lock;
492
493 if (lp->cur != DLM_LOCK_EX)
494 return;
495
496 init_completion(&lp->ast_wait);
497 set_bit(LFL_SYNC_LVB, &lp->flags);
498
499 lp->req = DLM_LOCK_EX;
500 lp->lkf = make_flags(lp, 0, lp->cur, lp->req);
501
502 gdlm_do_lock(lp, NULL);
503 wait_for_completion(&lp->ast_wait);
504}
505
506void gdlm_submit_delayed(struct gdlm_ls *ls)
507{
508 struct gdlm_lock *lp, *safe;
509
510 spin_lock(&ls->async_lock);
511 list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) {
512 list_del_init(&lp->delay_list);
513 list_add_tail(&lp->delay_list, &ls->submit);
514 }
515 spin_unlock(&ls->async_lock);
516 wake_up(&ls->thread_wait);
517}
518
519int gdlm_release_all_locks(struct gdlm_ls *ls)
520{
521 struct gdlm_lock *lp, *safe;
522 int count = 0;
523
524 spin_lock(&ls->async_lock);
525 list_for_each_entry_safe(lp, safe, &ls->all_locks, all_list) {
526 list_del_init(&lp->all_list);
527
528 if (lp->lvb && lp->lvb != junk_lvb)
529 kfree(lp->lvb);
530 kfree(lp);
531 count++;
532 }
533 spin_unlock(&ls->async_lock);
534
535 return count;
536}
537