blob: fed9a67be0f1248f18421e9a31a43f70e67da716 [file] [log] [blame]
David Teigland869d81d2006-01-17 08:47:12 +00001/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
Steven Whitehousee9fc2aa2006-09-01 11:05:15 -04007 * of the GNU General Public License version 2.
David Teigland869d81d2006-01-17 08:47:12 +00008 */
David Teigland29b79982006-01-16 16:52:38 +00009
10#include "lock_dlm.h"
11
12static char junk_lvb[GDLM_LVB_SIZE];
13
14static void queue_complete(struct gdlm_lock *lp)
15{
16 struct gdlm_ls *ls = lp->ls;
17
18 clear_bit(LFL_ACTIVE, &lp->flags);
19
20 spin_lock(&ls->async_lock);
21 list_add_tail(&lp->clist, &ls->complete);
22 spin_unlock(&ls->async_lock);
23 wake_up(&ls->thread_wait);
24}
25
26static inline void gdlm_ast(void *astarg)
27{
David Teiglande7f5c012006-04-27 11:25:45 -040028 queue_complete(astarg);
David Teigland29b79982006-01-16 16:52:38 +000029}
30
31static inline void gdlm_bast(void *astarg, int mode)
32{
33 struct gdlm_lock *lp = astarg;
34 struct gdlm_ls *ls = lp->ls;
35
36 if (!mode) {
Steven Whitehoused92a8d42006-02-27 10:57:14 -050037 printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n",
David Teigland9229f012006-05-24 09:21:30 -040038 lp->lockname.ln_type,
39 (unsigned long long)lp->lockname.ln_number);
David Teigland29b79982006-01-16 16:52:38 +000040 return;
41 }
42
43 spin_lock(&ls->async_lock);
44 if (!lp->bast_mode) {
45 list_add_tail(&lp->blist, &ls->blocking);
46 lp->bast_mode = mode;
47 } else if (lp->bast_mode < mode)
48 lp->bast_mode = mode;
49 spin_unlock(&ls->async_lock);
50 wake_up(&ls->thread_wait);
51}
52
53void gdlm_queue_delayed(struct gdlm_lock *lp)
54{
55 struct gdlm_ls *ls = lp->ls;
56
57 spin_lock(&ls->async_lock);
58 list_add_tail(&lp->delay_list, &ls->delayed);
59 spin_unlock(&ls->async_lock);
60}
61
62/* convert gfs lock-state to dlm lock-mode */
63
Steven Whitehousecd915492006-09-04 12:49:07 -040064static s16 make_mode(s16 lmstate)
David Teigland29b79982006-01-16 16:52:38 +000065{
66 switch (lmstate) {
67 case LM_ST_UNLOCKED:
68 return DLM_LOCK_NL;
69 case LM_ST_EXCLUSIVE:
70 return DLM_LOCK_EX;
71 case LM_ST_DEFERRED:
72 return DLM_LOCK_CW;
73 case LM_ST_SHARED:
74 return DLM_LOCK_PR;
David Teigland29b79982006-01-16 16:52:38 +000075 }
David Teigland869d81d2006-01-17 08:47:12 +000076 gdlm_assert(0, "unknown LM state %d", lmstate);
77 return -1;
David Teigland29b79982006-01-16 16:52:38 +000078}
79
80/* convert dlm lock-mode to gfs lock-state */
81
Steven Whitehousecd915492006-09-04 12:49:07 -040082s16 gdlm_make_lmstate(s16 dlmmode)
David Teigland29b79982006-01-16 16:52:38 +000083{
84 switch (dlmmode) {
85 case DLM_LOCK_IV:
86 case DLM_LOCK_NL:
87 return LM_ST_UNLOCKED;
88 case DLM_LOCK_EX:
89 return LM_ST_EXCLUSIVE;
90 case DLM_LOCK_CW:
91 return LM_ST_DEFERRED;
92 case DLM_LOCK_PR:
93 return LM_ST_SHARED;
David Teigland29b79982006-01-16 16:52:38 +000094 }
David Teigland869d81d2006-01-17 08:47:12 +000095 gdlm_assert(0, "unknown DLM mode %d", dlmmode);
96 return -1;
David Teigland29b79982006-01-16 16:52:38 +000097}
98
99/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and
100 DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */
101
102static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state)
103{
Steven Whitehousecd915492006-09-04 12:49:07 -0400104 s16 cur = make_mode(cur_state);
David Teigland29b79982006-01-16 16:52:38 +0000105 if (lp->cur != DLM_LOCK_IV)
David Teigland869d81d2006-01-17 08:47:12 +0000106 gdlm_assert(lp->cur == cur, "%d, %d", lp->cur, cur);
David Teigland29b79982006-01-16 16:52:38 +0000107}
108
109static inline unsigned int make_flags(struct gdlm_lock *lp,
110 unsigned int gfs_flags,
Steven Whitehousecd915492006-09-04 12:49:07 -0400111 s16 cur, s16 req)
David Teigland29b79982006-01-16 16:52:38 +0000112{
113 unsigned int lkf = 0;
114
115 if (gfs_flags & LM_FLAG_TRY)
116 lkf |= DLM_LKF_NOQUEUE;
117
118 if (gfs_flags & LM_FLAG_TRY_1CB) {
119 lkf |= DLM_LKF_NOQUEUE;
120 lkf |= DLM_LKF_NOQUEUEBAST;
121 }
122
123 if (gfs_flags & LM_FLAG_PRIORITY) {
124 lkf |= DLM_LKF_NOORDER;
125 lkf |= DLM_LKF_HEADQUE;
126 }
127
128 if (gfs_flags & LM_FLAG_ANY) {
129 if (req == DLM_LOCK_PR)
130 lkf |= DLM_LKF_ALTCW;
131 else if (req == DLM_LOCK_CW)
132 lkf |= DLM_LKF_ALTPR;
133 }
134
135 if (lp->lksb.sb_lkid != 0) {
136 lkf |= DLM_LKF_CONVERT;
137
138 /* Conversion deadlock avoidance by DLM */
139
Benjamin Marzinski58e9fee2008-03-14 13:52:52 -0500140 if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) &&
141 !test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
David Teigland29b79982006-01-16 16:52:38 +0000142 !(lkf & DLM_LKF_NOQUEUE) &&
143 cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
144 lkf |= DLM_LKF_CONVDEADLK;
145 }
146
147 if (lp->lvb)
148 lkf |= DLM_LKF_VALBLK;
149
150 return lkf;
151}
152
153/* make_strname - convert GFS lock numbers to a string */
154
Steven Whitehousef35ac342007-03-18 17:04:15 +0000155static inline void make_strname(const struct lm_lockname *lockname,
David Teigland29b79982006-01-16 16:52:38 +0000156 struct gdlm_strname *str)
157{
David Teigland869d81d2006-01-17 08:47:12 +0000158 sprintf(str->name, "%8x%16llx", lockname->ln_type,
David Teigland9229f012006-05-24 09:21:30 -0400159 (unsigned long long)lockname->ln_number);
David Teigland29b79982006-01-16 16:52:38 +0000160 str->namelen = GDLM_STRNAME_BYTES;
161}
162
Adrian Bunk08bc2db2006-04-28 10:59:12 -0400163static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
164 struct gdlm_lock **lpp)
David Teigland29b79982006-01-16 16:52:38 +0000165{
166 struct gdlm_lock *lp;
167
Josef Bacik16c5f062008-04-09 09:33:41 -0400168 lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
David Teigland29b79982006-01-16 16:52:38 +0000169 if (!lp)
170 return -ENOMEM;
171
David Teigland29b79982006-01-16 16:52:38 +0000172 lp->lockname = *name;
Steven Whitehousef35ac342007-03-18 17:04:15 +0000173 make_strname(name, &lp->strname);
David Teigland29b79982006-01-16 16:52:38 +0000174 lp->ls = ls;
175 lp->cur = DLM_LOCK_IV;
176 lp->lvb = NULL;
177 lp->hold_null = NULL;
David Teigland29b79982006-01-16 16:52:38 +0000178 INIT_LIST_HEAD(&lp->clist);
179 INIT_LIST_HEAD(&lp->blist);
180 INIT_LIST_HEAD(&lp->delay_list);
181
182 spin_lock(&ls->async_lock);
183 list_add(&lp->all_list, &ls->all_locks);
184 ls->all_locks_count++;
185 spin_unlock(&ls->async_lock);
186
187 *lpp = lp;
188 return 0;
189}
190
191void gdlm_delete_lp(struct gdlm_lock *lp)
192{
193 struct gdlm_ls *ls = lp->ls;
194
195 spin_lock(&ls->async_lock);
196 if (!list_empty(&lp->clist))
197 list_del_init(&lp->clist);
198 if (!list_empty(&lp->blist))
199 list_del_init(&lp->blist);
200 if (!list_empty(&lp->delay_list))
201 list_del_init(&lp->delay_list);
David Teigland9229f012006-05-24 09:21:30 -0400202 gdlm_assert(!list_empty(&lp->all_list), "%x,%llx", lp->lockname.ln_type,
203 (unsigned long long)lp->lockname.ln_number);
David Teigland29b79982006-01-16 16:52:38 +0000204 list_del_init(&lp->all_list);
205 ls->all_locks_count--;
206 spin_unlock(&ls->async_lock);
207
208 kfree(lp);
209}
210
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400211int gdlm_get_lock(void *lockspace, struct lm_lockname *name,
212 void **lockp)
David Teigland29b79982006-01-16 16:52:38 +0000213{
214 struct gdlm_lock *lp;
215 int error;
216
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400217 error = gdlm_create_lp(lockspace, name, &lp);
David Teigland29b79982006-01-16 16:52:38 +0000218
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400219 *lockp = lp;
David Teigland29b79982006-01-16 16:52:38 +0000220 return error;
221}
222
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400223void gdlm_put_lock(void *lock)
David Teigland29b79982006-01-16 16:52:38 +0000224{
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400225 gdlm_delete_lp(lock);
David Teigland29b79982006-01-16 16:52:38 +0000226}
227
David Teigland8d3b35a2006-02-23 10:00:56 +0000228unsigned int gdlm_do_lock(struct gdlm_lock *lp)
David Teigland29b79982006-01-16 16:52:38 +0000229{
230 struct gdlm_ls *ls = lp->ls;
David Teigland29b79982006-01-16 16:52:38 +0000231 int error, bast = 1;
232
233 /*
234 * When recovery is in progress, delay lock requests for submission
235 * once recovery is done. Requests for recovery (NOEXP) and unlocks
236 * can pass.
237 */
238
239 if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) &&
240 !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) {
241 gdlm_queue_delayed(lp);
David Teigland869d81d2006-01-17 08:47:12 +0000242 return LM_OUT_ASYNC;
David Teigland29b79982006-01-16 16:52:38 +0000243 }
244
245 /*
246 * Submit the actual lock request.
247 */
248
249 if (test_bit(LFL_NOBAST, &lp->flags))
250 bast = 0;
251
David Teigland29b79982006-01-16 16:52:38 +0000252 set_bit(LFL_ACTIVE, &lp->flags);
253
David Teigland869d81d2006-01-17 08:47:12 +0000254 log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type,
David Teigland9229f012006-05-24 09:21:30 -0400255 (unsigned long long)lp->lockname.ln_number, lp->lksb.sb_lkid,
David Teigland29b79982006-01-16 16:52:38 +0000256 lp->cur, lp->req, lp->lkf);
257
258 error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf,
Steven Whitehousef35ac342007-03-18 17:04:15 +0000259 lp->strname.name, lp->strname.namelen, 0, gdlm_ast,
260 lp, bast ? gdlm_bast : NULL);
David Teigland29b79982006-01-16 16:52:38 +0000261
262 if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) {
263 lp->lksb.sb_status = -EAGAIN;
264 queue_complete(lp);
265 error = 0;
266 }
267
David Teigland869d81d2006-01-17 08:47:12 +0000268 if (error) {
David Teiglandb9af8a72007-03-28 11:08:04 -0500269 log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x "
David Teigland869d81d2006-01-17 08:47:12 +0000270 "flags=%lx", ls->fsname, lp->lockname.ln_type,
David Teigland9229f012006-05-24 09:21:30 -0400271 (unsigned long long)lp->lockname.ln_number, error,
272 lp->cur, lp->req, lp->lkf, lp->flags);
David Teigland869d81d2006-01-17 08:47:12 +0000273 return LM_OUT_ERROR;
274 }
275 return LM_OUT_ASYNC;
David Teigland29b79982006-01-16 16:52:38 +0000276}
277
Adrian Bunk08bc2db2006-04-28 10:59:12 -0400278static unsigned int gdlm_do_unlock(struct gdlm_lock *lp)
David Teigland29b79982006-01-16 16:52:38 +0000279{
David Teigland869d81d2006-01-17 08:47:12 +0000280 struct gdlm_ls *ls = lp->ls;
David Teigland29b79982006-01-16 16:52:38 +0000281 unsigned int lkf = 0;
282 int error;
283
284 set_bit(LFL_DLM_UNLOCK, &lp->flags);
285 set_bit(LFL_ACTIVE, &lp->flags);
286
287 if (lp->lvb)
288 lkf = DLM_LKF_VALBLK;
289
David Teigland869d81d2006-01-17 08:47:12 +0000290 log_debug("un %x,%llx %x %d %x", lp->lockname.ln_type,
David Teigland9229f012006-05-24 09:21:30 -0400291 (unsigned long long)lp->lockname.ln_number,
292 lp->lksb.sb_lkid, lp->cur, lkf);
David Teigland29b79982006-01-16 16:52:38 +0000293
David Teigland869d81d2006-01-17 08:47:12 +0000294 error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp);
David Teigland29b79982006-01-16 16:52:38 +0000295
David Teigland869d81d2006-01-17 08:47:12 +0000296 if (error) {
David Teiglandb9af8a72007-03-28 11:08:04 -0500297 log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x "
David Teigland869d81d2006-01-17 08:47:12 +0000298 "flags=%lx", ls->fsname, lp->lockname.ln_type,
David Teigland9229f012006-05-24 09:21:30 -0400299 (unsigned long long)lp->lockname.ln_number, error,
300 lp->cur, lp->req, lp->lkf, lp->flags);
David Teigland869d81d2006-01-17 08:47:12 +0000301 return LM_OUT_ERROR;
302 }
303 return LM_OUT_ASYNC;
David Teigland29b79982006-01-16 16:52:38 +0000304}
305
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400306unsigned int gdlm_lock(void *lock, unsigned int cur_state,
David Teigland29b79982006-01-16 16:52:38 +0000307 unsigned int req_state, unsigned int flags)
308{
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400309 struct gdlm_lock *lp = lock;
David Teigland29b79982006-01-16 16:52:38 +0000310
Steven Whitehouse6802e342008-05-21 17:03:22 +0100311 if (req_state == LM_ST_UNLOCKED)
312 return gdlm_unlock(lock, cur_state);
313
David Teigland29b79982006-01-16 16:52:38 +0000314 clear_bit(LFL_DLM_CANCEL, &lp->flags);
315 if (flags & LM_FLAG_NOEXP)
316 set_bit(LFL_NOBLOCK, &lp->flags);
317
318 check_cur_state(lp, cur_state);
319 lp->req = make_mode(req_state);
320 lp->lkf = make_flags(lp, flags, lp->cur, lp->req);
321
David Teigland8d3b35a2006-02-23 10:00:56 +0000322 return gdlm_do_lock(lp);
David Teigland29b79982006-01-16 16:52:38 +0000323}
324
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400325unsigned int gdlm_unlock(void *lock, unsigned int cur_state)
David Teigland29b79982006-01-16 16:52:38 +0000326{
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400327 struct gdlm_lock *lp = lock;
David Teigland29b79982006-01-16 16:52:38 +0000328
329 clear_bit(LFL_DLM_CANCEL, &lp->flags);
330 if (lp->cur == DLM_LOCK_IV)
331 return 0;
David Teigland869d81d2006-01-17 08:47:12 +0000332 return gdlm_do_unlock(lp);
David Teigland29b79982006-01-16 16:52:38 +0000333}
334
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400335void gdlm_cancel(void *lock)
David Teigland29b79982006-01-16 16:52:38 +0000336{
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400337 struct gdlm_lock *lp = lock;
David Teigland29b79982006-01-16 16:52:38 +0000338 struct gdlm_ls *ls = lp->ls;
339 int error, delay_list = 0;
340
341 if (test_bit(LFL_DLM_CANCEL, &lp->flags))
342 return;
343
David Teigland9229f012006-05-24 09:21:30 -0400344 log_info("gdlm_cancel %x,%llx flags %lx", lp->lockname.ln_type,
345 (unsigned long long)lp->lockname.ln_number, lp->flags);
David Teigland29b79982006-01-16 16:52:38 +0000346
347 spin_lock(&ls->async_lock);
348 if (!list_empty(&lp->delay_list)) {
349 list_del_init(&lp->delay_list);
350 delay_list = 1;
351 }
352 spin_unlock(&ls->async_lock);
353
354 if (delay_list) {
355 set_bit(LFL_CANCEL, &lp->flags);
356 set_bit(LFL_ACTIVE, &lp->flags);
357 queue_complete(lp);
358 return;
359 }
360
361 if (!test_bit(LFL_ACTIVE, &lp->flags) ||
David Teigland9229f012006-05-24 09:21:30 -0400362 test_bit(LFL_DLM_UNLOCK, &lp->flags)) {
David Teigland869d81d2006-01-17 08:47:12 +0000363 log_info("gdlm_cancel skip %x,%llx flags %lx",
David Teigland9229f012006-05-24 09:21:30 -0400364 lp->lockname.ln_type,
365 (unsigned long long)lp->lockname.ln_number, lp->flags);
David Teigland29b79982006-01-16 16:52:38 +0000366 return;
367 }
368
369 /* the lock is blocked in the dlm */
370
371 set_bit(LFL_DLM_CANCEL, &lp->flags);
372 set_bit(LFL_ACTIVE, &lp->flags);
373
374 error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL,
375 NULL, lp);
376
David Teigland869d81d2006-01-17 08:47:12 +0000377 log_info("gdlm_cancel rv %d %x,%llx flags %lx", error,
David Teigland9229f012006-05-24 09:21:30 -0400378 lp->lockname.ln_type,
379 (unsigned long long)lp->lockname.ln_number, lp->flags);
David Teigland29b79982006-01-16 16:52:38 +0000380
381 if (error == -EBUSY)
382 clear_bit(LFL_DLM_CANCEL, &lp->flags);
383}
384
Adrian Bunk08bc2db2006-04-28 10:59:12 -0400385static int gdlm_add_lvb(struct gdlm_lock *lp)
David Teigland29b79982006-01-16 16:52:38 +0000386{
387 char *lvb;
388
Josef Bacik16c5f062008-04-09 09:33:41 -0400389 lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
David Teigland29b79982006-01-16 16:52:38 +0000390 if (!lvb)
391 return -ENOMEM;
392
David Teigland29b79982006-01-16 16:52:38 +0000393 lp->lksb.sb_lvbptr = lvb;
394 lp->lvb = lvb;
395 return 0;
396}
397
Adrian Bunk08bc2db2006-04-28 10:59:12 -0400398static void gdlm_del_lvb(struct gdlm_lock *lp)
David Teigland29b79982006-01-16 16:52:38 +0000399{
400 kfree(lp->lvb);
401 lp->lvb = NULL;
402 lp->lksb.sb_lvbptr = NULL;
403}
404
Steven Whitehouse41d7db02007-05-14 17:43:26 +0100405static int gdlm_ast_wait(void *word)
406{
407 schedule();
408 return 0;
409}
410
David Teigland29b79982006-01-16 16:52:38 +0000411/* This can do a synchronous dlm request (requiring a lock_dlm thread to get
412 the completion) because gfs won't call hold_lvb() during a callback (from
413 the context of a lock_dlm thread). */
414
415static int hold_null_lock(struct gdlm_lock *lp)
416{
417 struct gdlm_lock *lpn = NULL;
418 int error;
419
420 if (lp->hold_null) {
Steven Whitehoused92a8d42006-02-27 10:57:14 -0500421 printk(KERN_INFO "lock_dlm: lvb already held\n");
David Teigland29b79982006-01-16 16:52:38 +0000422 return 0;
423 }
424
425 error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn);
426 if (error)
427 goto out;
428
429 lpn->lksb.sb_lvbptr = junk_lvb;
430 lpn->lvb = junk_lvb;
431
432 lpn->req = DLM_LOCK_NL;
433 lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
434 set_bit(LFL_NOBAST, &lpn->flags);
435 set_bit(LFL_INLOCK, &lpn->flags);
Steven Whitehouse41d7db02007-05-14 17:43:26 +0100436 set_bit(LFL_AST_WAIT, &lpn->flags);
David Teigland29b79982006-01-16 16:52:38 +0000437
David Teigland8d3b35a2006-02-23 10:00:56 +0000438 gdlm_do_lock(lpn);
Steven Whitehouse41d7db02007-05-14 17:43:26 +0100439 wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
David Teiglandc5921fd2006-07-20 09:06:34 -0500440 error = lpn->lksb.sb_status;
David Teigland29b79982006-01-16 16:52:38 +0000441 if (error) {
Steven Whitehoused92a8d42006-02-27 10:57:14 -0500442 printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
443 error);
David Teigland29b79982006-01-16 16:52:38 +0000444 gdlm_delete_lp(lpn);
445 lpn = NULL;
446 }
Steven Whitehousea91ea692006-09-04 12:04:26 -0400447out:
David Teigland29b79982006-01-16 16:52:38 +0000448 lp->hold_null = lpn;
449 return error;
450}
451
452/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get
453 the completion) because gfs may call unhold_lvb() during a callback (from
454 the context of a lock_dlm thread) which could cause a deadlock since the
455 other lock_dlm thread could be engaged in recovery. */
456
457static void unhold_null_lock(struct gdlm_lock *lp)
458{
459 struct gdlm_lock *lpn = lp->hold_null;
460
David Teigland9229f012006-05-24 09:21:30 -0400461 gdlm_assert(lpn, "%x,%llx", lp->lockname.ln_type,
462 (unsigned long long)lp->lockname.ln_number);
David Teigland29b79982006-01-16 16:52:38 +0000463 lpn->lksb.sb_lvbptr = NULL;
464 lpn->lvb = NULL;
465 set_bit(LFL_UNLOCK_DELETE, &lpn->flags);
466 gdlm_do_unlock(lpn);
467 lp->hold_null = NULL;
468}
469
470/* Acquire a NL lock because gfs requires the value block to remain
471 intact on the resource while the lvb is "held" even if it's holding no locks
472 on the resource. */
473
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400474int gdlm_hold_lvb(void *lock, char **lvbp)
David Teigland29b79982006-01-16 16:52:38 +0000475{
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400476 struct gdlm_lock *lp = lock;
David Teigland29b79982006-01-16 16:52:38 +0000477 int error;
478
479 error = gdlm_add_lvb(lp);
480 if (error)
481 return error;
482
483 *lvbp = lp->lvb;
484
485 error = hold_null_lock(lp);
486 if (error)
487 gdlm_del_lvb(lp);
488
489 return error;
490}
491
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400492void gdlm_unhold_lvb(void *lock, char *lvb)
David Teigland29b79982006-01-16 16:52:38 +0000493{
Steven Whitehouse9b47c112006-09-08 10:17:58 -0400494 struct gdlm_lock *lp = lock;
David Teigland29b79982006-01-16 16:52:38 +0000495
496 unhold_null_lock(lp);
497 gdlm_del_lvb(lp);
498}
499
David Teigland29b79982006-01-16 16:52:38 +0000500void gdlm_submit_delayed(struct gdlm_ls *ls)
501{
502 struct gdlm_lock *lp, *safe;
503
504 spin_lock(&ls->async_lock);
505 list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) {
506 list_del_init(&lp->delay_list);
507 list_add_tail(&lp->delay_list, &ls->submit);
508 }
509 spin_unlock(&ls->async_lock);
510 wake_up(&ls->thread_wait);
511}
512
513int gdlm_release_all_locks(struct gdlm_ls *ls)
514{
515 struct gdlm_lock *lp, *safe;
516 int count = 0;
517
518 spin_lock(&ls->async_lock);
519 list_for_each_entry_safe(lp, safe, &ls->all_locks, all_list) {
520 list_del_init(&lp->all_list);
521
522 if (lp->lvb && lp->lvb != junk_lvb)
523 kfree(lp->lvb);
524 kfree(lp);
525 count++;
526 }
527 spin_unlock(&ls->async_lock);
528
529 return count;
530}
531