diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-15 21:07:59 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-15 21:07:59 -0400 |
commit | 84c3d4aaec3338201b449034beac41635866bddf (patch) | |
tree | 3412951682fb2dd4feb8a5532f8efbaf8b345933 /fs/gfs2/locking | |
parent | 43d2548bb2ef7e6d753f91468a746784041e522d (diff) | |
parent | fafa3a3f16723997f039a0193997464d66dafd8f (diff) |
Merge commit 'origin/master'
Manual merge of:
arch/powerpc/Kconfig
arch/powerpc/kernel/stacktrace.c
arch/powerpc/mm/slice.c
arch/ppc/kernel/smp.c
Diffstat (limited to 'fs/gfs2/locking')
-rw-r--r-- | fs/gfs2/locking/dlm/lock.c | 368 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/lock_dlm.h | 18 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/mount.c | 14 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/sysfs.c | 13 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/thread.c | 331 | ||||
-rw-r--r-- | fs/gfs2/locking/nolock/Makefile | 3 | ||||
-rw-r--r-- | fs/gfs2/locking/nolock/main.c | 238 |
7 files changed, 288 insertions, 697 deletions
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c index cf7ea8abec87..2482c9047505 100644 --- a/fs/gfs2/locking/dlm/lock.c +++ b/fs/gfs2/locking/dlm/lock.c | |||
@@ -11,46 +11,60 @@ | |||
11 | 11 | ||
12 | static char junk_lvb[GDLM_LVB_SIZE]; | 12 | static char junk_lvb[GDLM_LVB_SIZE]; |
13 | 13 | ||
14 | static void queue_complete(struct gdlm_lock *lp) | 14 | |
15 | /* convert dlm lock-mode to gfs lock-state */ | ||
16 | |||
17 | static s16 gdlm_make_lmstate(s16 dlmmode) | ||
15 | { | 18 | { |
16 | struct gdlm_ls *ls = lp->ls; | 19 | switch (dlmmode) { |
20 | case DLM_LOCK_IV: | ||
21 | case DLM_LOCK_NL: | ||
22 | return LM_ST_UNLOCKED; | ||
23 | case DLM_LOCK_EX: | ||
24 | return LM_ST_EXCLUSIVE; | ||
25 | case DLM_LOCK_CW: | ||
26 | return LM_ST_DEFERRED; | ||
27 | case DLM_LOCK_PR: | ||
28 | return LM_ST_SHARED; | ||
29 | } | ||
30 | gdlm_assert(0, "unknown DLM mode %d", dlmmode); | ||
31 | return -1; | ||
32 | } | ||
17 | 33 | ||
18 | clear_bit(LFL_ACTIVE, &lp->flags); | 34 | /* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm |
35 | thread gets to it. */ | ||
36 | |||
37 | static void queue_submit(struct gdlm_lock *lp) | ||
38 | { | ||
39 | struct gdlm_ls *ls = lp->ls; | ||
19 | 40 | ||
20 | spin_lock(&ls->async_lock); | 41 | spin_lock(&ls->async_lock); |
21 | list_add_tail(&lp->clist, &ls->complete); | 42 | list_add_tail(&lp->delay_list, &ls->submit); |
22 | spin_unlock(&ls->async_lock); | 43 | spin_unlock(&ls->async_lock); |
23 | wake_up(&ls->thread_wait); | 44 | wake_up(&ls->thread_wait); |
24 | } | 45 | } |
25 | 46 | ||
26 | static inline void gdlm_ast(void *astarg) | 47 | static void wake_up_ast(struct gdlm_lock *lp) |
27 | { | 48 | { |
28 | queue_complete(astarg); | 49 | clear_bit(LFL_AST_WAIT, &lp->flags); |
50 | smp_mb__after_clear_bit(); | ||
51 | wake_up_bit(&lp->flags, LFL_AST_WAIT); | ||
29 | } | 52 | } |
30 | 53 | ||
31 | static inline void gdlm_bast(void *astarg, int mode) | 54 | static void gdlm_delete_lp(struct gdlm_lock *lp) |
32 | { | 55 | { |
33 | struct gdlm_lock *lp = astarg; | ||
34 | struct gdlm_ls *ls = lp->ls; | 56 | struct gdlm_ls *ls = lp->ls; |
35 | 57 | ||
36 | if (!mode) { | ||
37 | printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n", | ||
38 | lp->lockname.ln_type, | ||
39 | (unsigned long long)lp->lockname.ln_number); | ||
40 | return; | ||
41 | } | ||
42 | |||
43 | spin_lock(&ls->async_lock); | 58 | spin_lock(&ls->async_lock); |
44 | if (!lp->bast_mode) { | 59 | if (!list_empty(&lp->delay_list)) |
45 | list_add_tail(&lp->blist, &ls->blocking); | 60 | list_del_init(&lp->delay_list); |
46 | lp->bast_mode = mode; | 61 | ls->all_locks_count--; |
47 | } else if (lp->bast_mode < mode) | ||
48 | lp->bast_mode = mode; | ||
49 | spin_unlock(&ls->async_lock); | 62 | spin_unlock(&ls->async_lock); |
50 | wake_up(&ls->thread_wait); | 63 | |
64 | kfree(lp); | ||
51 | } | 65 | } |
52 | 66 | ||
53 | void gdlm_queue_delayed(struct gdlm_lock *lp) | 67 | static void gdlm_queue_delayed(struct gdlm_lock *lp) |
54 | { | 68 | { |
55 | struct gdlm_ls *ls = lp->ls; | 69 | struct gdlm_ls *ls = lp->ls; |
56 | 70 | ||
@@ -59,6 +73,236 @@ void gdlm_queue_delayed(struct gdlm_lock *lp) | |||
59 | spin_unlock(&ls->async_lock); | 73 | spin_unlock(&ls->async_lock); |
60 | } | 74 | } |
61 | 75 | ||
76 | static void process_complete(struct gdlm_lock *lp) | ||
77 | { | ||
78 | struct gdlm_ls *ls = lp->ls; | ||
79 | struct lm_async_cb acb; | ||
80 | |||
81 | memset(&acb, 0, sizeof(acb)); | ||
82 | |||
83 | if (lp->lksb.sb_status == -DLM_ECANCEL) { | ||
84 | log_info("complete dlm cancel %x,%llx flags %lx", | ||
85 | lp->lockname.ln_type, | ||
86 | (unsigned long long)lp->lockname.ln_number, | ||
87 | lp->flags); | ||
88 | |||
89 | lp->req = lp->cur; | ||
90 | acb.lc_ret |= LM_OUT_CANCELED; | ||
91 | if (lp->cur == DLM_LOCK_IV) | ||
92 | lp->lksb.sb_lkid = 0; | ||
93 | goto out; | ||
94 | } | ||
95 | |||
96 | if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) { | ||
97 | if (lp->lksb.sb_status != -DLM_EUNLOCK) { | ||
98 | log_info("unlock sb_status %d %x,%llx flags %lx", | ||
99 | lp->lksb.sb_status, lp->lockname.ln_type, | ||
100 | (unsigned long long)lp->lockname.ln_number, | ||
101 | lp->flags); | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | lp->cur = DLM_LOCK_IV; | ||
106 | lp->req = DLM_LOCK_IV; | ||
107 | lp->lksb.sb_lkid = 0; | ||
108 | |||
109 | if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) { | ||
110 | gdlm_delete_lp(lp); | ||
111 | return; | ||
112 | } | ||
113 | goto out; | ||
114 | } | ||
115 | |||
116 | if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID) | ||
117 | memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE); | ||
118 | |||
119 | if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) { | ||
120 | if (lp->req == DLM_LOCK_PR) | ||
121 | lp->req = DLM_LOCK_CW; | ||
122 | else if (lp->req == DLM_LOCK_CW) | ||
123 | lp->req = DLM_LOCK_PR; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * A canceled lock request. The lock was just taken off the delayed | ||
128 | * list and was never even submitted to dlm. | ||
129 | */ | ||
130 | |||
131 | if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) { | ||
132 | log_info("complete internal cancel %x,%llx", | ||
133 | lp->lockname.ln_type, | ||
134 | (unsigned long long)lp->lockname.ln_number); | ||
135 | lp->req = lp->cur; | ||
136 | acb.lc_ret |= LM_OUT_CANCELED; | ||
137 | goto out; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * An error occured. | ||
142 | */ | ||
143 | |||
144 | if (lp->lksb.sb_status) { | ||
145 | /* a "normal" error */ | ||
146 | if ((lp->lksb.sb_status == -EAGAIN) && | ||
147 | (lp->lkf & DLM_LKF_NOQUEUE)) { | ||
148 | lp->req = lp->cur; | ||
149 | if (lp->cur == DLM_LOCK_IV) | ||
150 | lp->lksb.sb_lkid = 0; | ||
151 | goto out; | ||
152 | } | ||
153 | |||
154 | /* this could only happen with cancels I think */ | ||
155 | log_info("ast sb_status %d %x,%llx flags %lx", | ||
156 | lp->lksb.sb_status, lp->lockname.ln_type, | ||
157 | (unsigned long long)lp->lockname.ln_number, | ||
158 | lp->flags); | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * This is an AST for an EX->EX conversion for sync_lvb from GFS. | ||
164 | */ | ||
165 | |||
166 | if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { | ||
167 | wake_up_ast(lp); | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * A lock has been demoted to NL because it initially completed during | ||
173 | * BLOCK_LOCKS. Now it must be requested in the originally requested | ||
174 | * mode. | ||
175 | */ | ||
176 | |||
177 | if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) { | ||
178 | gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx", | ||
179 | lp->lockname.ln_type, | ||
180 | (unsigned long long)lp->lockname.ln_number); | ||
181 | gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx", | ||
182 | lp->lockname.ln_type, | ||
183 | (unsigned long long)lp->lockname.ln_number); | ||
184 | |||
185 | lp->cur = DLM_LOCK_NL; | ||
186 | lp->req = lp->prev_req; | ||
187 | lp->prev_req = DLM_LOCK_IV; | ||
188 | lp->lkf &= ~DLM_LKF_CONVDEADLK; | ||
189 | |||
190 | set_bit(LFL_NOCACHE, &lp->flags); | ||
191 | |||
192 | if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && | ||
193 | !test_bit(LFL_NOBLOCK, &lp->flags)) | ||
194 | gdlm_queue_delayed(lp); | ||
195 | else | ||
196 | queue_submit(lp); | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * A request is granted during dlm recovery. It may be granted | ||
202 | * because the locks of a failed node were cleared. In that case, | ||
203 | * there may be inconsistent data beneath this lock and we must wait | ||
204 | * for recovery to complete to use it. When gfs recovery is done this | ||
205 | * granted lock will be converted to NL and then reacquired in this | ||
206 | * granted state. | ||
207 | */ | ||
208 | |||
209 | if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && | ||
210 | !test_bit(LFL_NOBLOCK, &lp->flags) && | ||
211 | lp->req != DLM_LOCK_NL) { | ||
212 | |||
213 | lp->cur = lp->req; | ||
214 | lp->prev_req = lp->req; | ||
215 | lp->req = DLM_LOCK_NL; | ||
216 | lp->lkf |= DLM_LKF_CONVERT; | ||
217 | lp->lkf &= ~DLM_LKF_CONVDEADLK; | ||
218 | |||
219 | log_debug("rereq %x,%llx id %x %d,%d", | ||
220 | lp->lockname.ln_type, | ||
221 | (unsigned long long)lp->lockname.ln_number, | ||
222 | lp->lksb.sb_lkid, lp->cur, lp->req); | ||
223 | |||
224 | set_bit(LFL_REREQUEST, &lp->flags); | ||
225 | queue_submit(lp); | ||
226 | return; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * DLM demoted the lock to NL before it was granted so GFS must be | ||
231 | * told it cannot cache data for this lock. | ||
232 | */ | ||
233 | |||
234 | if (lp->lksb.sb_flags & DLM_SBF_DEMOTED) | ||
235 | set_bit(LFL_NOCACHE, &lp->flags); | ||
236 | |||
237 | out: | ||
238 | /* | ||
239 | * This is an internal lock_dlm lock | ||
240 | */ | ||
241 | |||
242 | if (test_bit(LFL_INLOCK, &lp->flags)) { | ||
243 | clear_bit(LFL_NOBLOCK, &lp->flags); | ||
244 | lp->cur = lp->req; | ||
245 | wake_up_ast(lp); | ||
246 | return; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Normal completion of a lock request. Tell GFS it now has the lock. | ||
251 | */ | ||
252 | |||
253 | clear_bit(LFL_NOBLOCK, &lp->flags); | ||
254 | lp->cur = lp->req; | ||
255 | |||
256 | acb.lc_name = lp->lockname; | ||
257 | acb.lc_ret |= gdlm_make_lmstate(lp->cur); | ||
258 | |||
259 | ls->fscb(ls->sdp, LM_CB_ASYNC, &acb); | ||
260 | } | ||
261 | |||
262 | static void gdlm_ast(void *astarg) | ||
263 | { | ||
264 | struct gdlm_lock *lp = astarg; | ||
265 | clear_bit(LFL_ACTIVE, &lp->flags); | ||
266 | process_complete(lp); | ||
267 | } | ||
268 | |||
269 | static void process_blocking(struct gdlm_lock *lp, int bast_mode) | ||
270 | { | ||
271 | struct gdlm_ls *ls = lp->ls; | ||
272 | unsigned int cb = 0; | ||
273 | |||
274 | switch (gdlm_make_lmstate(bast_mode)) { | ||
275 | case LM_ST_EXCLUSIVE: | ||
276 | cb = LM_CB_NEED_E; | ||
277 | break; | ||
278 | case LM_ST_DEFERRED: | ||
279 | cb = LM_CB_NEED_D; | ||
280 | break; | ||
281 | case LM_ST_SHARED: | ||
282 | cb = LM_CB_NEED_S; | ||
283 | break; | ||
284 | default: | ||
285 | gdlm_assert(0, "unknown bast mode %u", bast_mode); | ||
286 | } | ||
287 | |||
288 | ls->fscb(ls->sdp, cb, &lp->lockname); | ||
289 | } | ||
290 | |||
291 | |||
292 | static void gdlm_bast(void *astarg, int mode) | ||
293 | { | ||
294 | struct gdlm_lock *lp = astarg; | ||
295 | |||
296 | if (!mode) { | ||
297 | printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n", | ||
298 | lp->lockname.ln_type, | ||
299 | (unsigned long long)lp->lockname.ln_number); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | process_blocking(lp, mode); | ||
304 | } | ||
305 | |||
62 | /* convert gfs lock-state to dlm lock-mode */ | 306 | /* convert gfs lock-state to dlm lock-mode */ |
63 | 307 | ||
64 | static s16 make_mode(s16 lmstate) | 308 | static s16 make_mode(s16 lmstate) |
@@ -77,24 +321,6 @@ static s16 make_mode(s16 lmstate) | |||
77 | return -1; | 321 | return -1; |
78 | } | 322 | } |
79 | 323 | ||
80 | /* convert dlm lock-mode to gfs lock-state */ | ||
81 | |||
82 | s16 gdlm_make_lmstate(s16 dlmmode) | ||
83 | { | ||
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; | ||
94 | } | ||
95 | gdlm_assert(0, "unknown DLM mode %d", dlmmode); | ||
96 | return -1; | ||
97 | } | ||
98 | 324 | ||
99 | /* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and | 325 | /* 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. */ | 326 | DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */ |
@@ -134,14 +360,6 @@ static inline unsigned int make_flags(struct gdlm_lock *lp, | |||
134 | 360 | ||
135 | if (lp->lksb.sb_lkid != 0) { | 361 | if (lp->lksb.sb_lkid != 0) { |
136 | lkf |= DLM_LKF_CONVERT; | 362 | lkf |= DLM_LKF_CONVERT; |
137 | |||
138 | /* Conversion deadlock avoidance by DLM */ | ||
139 | |||
140 | if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) && | ||
141 | !test_bit(LFL_FORCE_PROMOTE, &lp->flags) && | ||
142 | !(lkf & DLM_LKF_NOQUEUE) && | ||
143 | cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) | ||
144 | lkf |= DLM_LKF_CONVDEADLK; | ||
145 | } | 363 | } |
146 | 364 | ||
147 | if (lp->lvb) | 365 | if (lp->lvb) |
@@ -173,14 +391,9 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, | |||
173 | make_strname(name, &lp->strname); | 391 | make_strname(name, &lp->strname); |
174 | lp->ls = ls; | 392 | lp->ls = ls; |
175 | lp->cur = DLM_LOCK_IV; | 393 | lp->cur = DLM_LOCK_IV; |
176 | lp->lvb = NULL; | ||
177 | lp->hold_null = NULL; | ||
178 | INIT_LIST_HEAD(&lp->clist); | ||
179 | INIT_LIST_HEAD(&lp->blist); | ||
180 | INIT_LIST_HEAD(&lp->delay_list); | 394 | INIT_LIST_HEAD(&lp->delay_list); |
181 | 395 | ||
182 | spin_lock(&ls->async_lock); | 396 | spin_lock(&ls->async_lock); |
183 | list_add(&lp->all_list, &ls->all_locks); | ||
184 | ls->all_locks_count++; | 397 | ls->all_locks_count++; |
185 | spin_unlock(&ls->async_lock); | 398 | spin_unlock(&ls->async_lock); |
186 | 399 | ||
@@ -188,26 +401,6 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, | |||
188 | return 0; | 401 | return 0; |
189 | } | 402 | } |
190 | 403 | ||
191 | void 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); | ||
202 | gdlm_assert(!list_empty(&lp->all_list), "%x,%llx", lp->lockname.ln_type, | ||
203 | (unsigned long long)lp->lockname.ln_number); | ||
204 | list_del_init(&lp->all_list); | ||
205 | ls->all_locks_count--; | ||
206 | spin_unlock(&ls->async_lock); | ||
207 | |||
208 | kfree(lp); | ||
209 | } | ||
210 | |||
211 | int gdlm_get_lock(void *lockspace, struct lm_lockname *name, | 404 | int gdlm_get_lock(void *lockspace, struct lm_lockname *name, |
212 | void **lockp) | 405 | void **lockp) |
213 | { | 406 | { |
@@ -261,7 +454,7 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp) | |||
261 | 454 | ||
262 | if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { | 455 | if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { |
263 | lp->lksb.sb_status = -EAGAIN; | 456 | lp->lksb.sb_status = -EAGAIN; |
264 | queue_complete(lp); | 457 | gdlm_ast(lp); |
265 | error = 0; | 458 | error = 0; |
266 | } | 459 | } |
267 | 460 | ||
@@ -308,6 +501,12 @@ unsigned int gdlm_lock(void *lock, unsigned int cur_state, | |||
308 | { | 501 | { |
309 | struct gdlm_lock *lp = lock; | 502 | struct gdlm_lock *lp = lock; |
310 | 503 | ||
504 | if (req_state == LM_ST_UNLOCKED) | ||
505 | return gdlm_unlock(lock, cur_state); | ||
506 | |||
507 | if (req_state == LM_ST_UNLOCKED) | ||
508 | return gdlm_unlock(lock, cur_state); | ||
509 | |||
311 | clear_bit(LFL_DLM_CANCEL, &lp->flags); | 510 | clear_bit(LFL_DLM_CANCEL, &lp->flags); |
312 | if (flags & LM_FLAG_NOEXP) | 511 | if (flags & LM_FLAG_NOEXP) |
313 | set_bit(LFL_NOBLOCK, &lp->flags); | 512 | set_bit(LFL_NOBLOCK, &lp->flags); |
@@ -351,7 +550,7 @@ void gdlm_cancel(void *lock) | |||
351 | if (delay_list) { | 550 | if (delay_list) { |
352 | set_bit(LFL_CANCEL, &lp->flags); | 551 | set_bit(LFL_CANCEL, &lp->flags); |
353 | set_bit(LFL_ACTIVE, &lp->flags); | 552 | set_bit(LFL_ACTIVE, &lp->flags); |
354 | queue_complete(lp); | 553 | gdlm_ast(lp); |
355 | return; | 554 | return; |
356 | } | 555 | } |
357 | 556 | ||
@@ -507,22 +706,3 @@ void gdlm_submit_delayed(struct gdlm_ls *ls) | |||
507 | wake_up(&ls->thread_wait); | 706 | wake_up(&ls->thread_wait); |
508 | } | 707 | } |
509 | 708 | ||
510 | int gdlm_release_all_locks(struct gdlm_ls *ls) | ||
511 | { | ||
512 | struct gdlm_lock *lp, *safe; | ||
513 | int count = 0; | ||
514 | |||
515 | spin_lock(&ls->async_lock); | ||
516 | list_for_each_entry_safe(lp, safe, &ls->all_locks, all_list) { | ||
517 | list_del_init(&lp->all_list); | ||
518 | |||
519 | if (lp->lvb && lp->lvb != junk_lvb) | ||
520 | kfree(lp->lvb); | ||
521 | kfree(lp); | ||
522 | count++; | ||
523 | } | ||
524 | spin_unlock(&ls->async_lock); | ||
525 | |||
526 | return count; | ||
527 | } | ||
528 | |||
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h index a243cf69c54e..3c98e7c6f93b 100644 --- a/fs/gfs2/locking/dlm/lock_dlm.h +++ b/fs/gfs2/locking/dlm/lock_dlm.h | |||
@@ -72,19 +72,12 @@ struct gdlm_ls { | |||
72 | int recover_jid_done; | 72 | int recover_jid_done; |
73 | int recover_jid_status; | 73 | int recover_jid_status; |
74 | spinlock_t async_lock; | 74 | spinlock_t async_lock; |
75 | struct list_head complete; | ||
76 | struct list_head blocking; | ||
77 | struct list_head delayed; | 75 | struct list_head delayed; |
78 | struct list_head submit; | 76 | struct list_head submit; |
79 | struct list_head all_locks; | ||
80 | u32 all_locks_count; | 77 | u32 all_locks_count; |
81 | wait_queue_head_t wait_control; | 78 | wait_queue_head_t wait_control; |
82 | struct task_struct *thread1; | 79 | struct task_struct *thread; |
83 | struct task_struct *thread2; | ||
84 | wait_queue_head_t thread_wait; | 80 | wait_queue_head_t thread_wait; |
85 | unsigned long drop_time; | ||
86 | int drop_locks_count; | ||
87 | int drop_locks_period; | ||
88 | }; | 81 | }; |
89 | 82 | ||
90 | enum { | 83 | enum { |
@@ -117,12 +110,7 @@ struct gdlm_lock { | |||
117 | u32 lkf; /* dlm flags DLM_LKF_ */ | 110 | u32 lkf; /* dlm flags DLM_LKF_ */ |
118 | unsigned long flags; /* lock_dlm flags LFL_ */ | 111 | unsigned long flags; /* lock_dlm flags LFL_ */ |
119 | 112 | ||
120 | int bast_mode; /* protected by async_lock */ | ||
121 | |||
122 | struct list_head clist; /* complete */ | ||
123 | struct list_head blist; /* blocking */ | ||
124 | struct list_head delay_list; /* delayed */ | 113 | struct list_head delay_list; /* delayed */ |
125 | struct list_head all_list; /* all locks for the fs */ | ||
126 | struct gdlm_lock *hold_null; /* NL lock for hold_lvb */ | 114 | struct gdlm_lock *hold_null; /* NL lock for hold_lvb */ |
127 | }; | 115 | }; |
128 | 116 | ||
@@ -159,11 +147,7 @@ void gdlm_release_threads(struct gdlm_ls *); | |||
159 | 147 | ||
160 | /* lock.c */ | 148 | /* lock.c */ |
161 | 149 | ||
162 | s16 gdlm_make_lmstate(s16); | ||
163 | void gdlm_queue_delayed(struct gdlm_lock *); | ||
164 | void gdlm_submit_delayed(struct gdlm_ls *); | 150 | void gdlm_submit_delayed(struct gdlm_ls *); |
165 | int gdlm_release_all_locks(struct gdlm_ls *); | ||
166 | void gdlm_delete_lp(struct gdlm_lock *); | ||
167 | unsigned int gdlm_do_lock(struct gdlm_lock *); | 151 | unsigned int gdlm_do_lock(struct gdlm_lock *); |
168 | 152 | ||
169 | int gdlm_get_lock(void *, struct lm_lockname *, void **); | 153 | int gdlm_get_lock(void *, struct lm_lockname *, void **); |
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c index 470bdf650b50..09d78c216f48 100644 --- a/fs/gfs2/locking/dlm/mount.c +++ b/fs/gfs2/locking/dlm/mount.c | |||
@@ -22,22 +22,14 @@ static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp, | |||
22 | if (!ls) | 22 | if (!ls) |
23 | return NULL; | 23 | return NULL; |
24 | 24 | ||
25 | ls->drop_locks_count = GDLM_DROP_COUNT; | ||
26 | ls->drop_locks_period = GDLM_DROP_PERIOD; | ||
27 | ls->fscb = cb; | 25 | ls->fscb = cb; |
28 | ls->sdp = sdp; | 26 | ls->sdp = sdp; |
29 | ls->fsflags = flags; | 27 | ls->fsflags = flags; |
30 | spin_lock_init(&ls->async_lock); | 28 | spin_lock_init(&ls->async_lock); |
31 | INIT_LIST_HEAD(&ls->complete); | ||
32 | INIT_LIST_HEAD(&ls->blocking); | ||
33 | INIT_LIST_HEAD(&ls->delayed); | 29 | INIT_LIST_HEAD(&ls->delayed); |
34 | INIT_LIST_HEAD(&ls->submit); | 30 | INIT_LIST_HEAD(&ls->submit); |
35 | INIT_LIST_HEAD(&ls->all_locks); | ||
36 | init_waitqueue_head(&ls->thread_wait); | 31 | init_waitqueue_head(&ls->thread_wait); |
37 | init_waitqueue_head(&ls->wait_control); | 32 | init_waitqueue_head(&ls->wait_control); |
38 | ls->thread1 = NULL; | ||
39 | ls->thread2 = NULL; | ||
40 | ls->drop_time = jiffies; | ||
41 | ls->jid = -1; | 33 | ls->jid = -1; |
42 | 34 | ||
43 | strncpy(buf, table_name, 256); | 35 | strncpy(buf, table_name, 256); |
@@ -180,7 +172,6 @@ out: | |||
180 | static void gdlm_unmount(void *lockspace) | 172 | static void gdlm_unmount(void *lockspace) |
181 | { | 173 | { |
182 | struct gdlm_ls *ls = lockspace; | 174 | struct gdlm_ls *ls = lockspace; |
183 | int rv; | ||
184 | 175 | ||
185 | log_debug("unmount flags %lx", ls->flags); | 176 | log_debug("unmount flags %lx", ls->flags); |
186 | 177 | ||
@@ -194,9 +185,7 @@ static void gdlm_unmount(void *lockspace) | |||
194 | gdlm_kobject_release(ls); | 185 | gdlm_kobject_release(ls); |
195 | dlm_release_lockspace(ls->dlm_lockspace, 2); | 186 | dlm_release_lockspace(ls->dlm_lockspace, 2); |
196 | gdlm_release_threads(ls); | 187 | gdlm_release_threads(ls); |
197 | rv = gdlm_release_all_locks(ls); | 188 | BUG_ON(ls->all_locks_count); |
198 | if (rv) | ||
199 | log_info("gdlm_unmount: %d stray locks freed", rv); | ||
200 | out: | 189 | out: |
201 | kfree(ls); | 190 | kfree(ls); |
202 | } | 191 | } |
@@ -232,7 +221,6 @@ static void gdlm_withdraw(void *lockspace) | |||
232 | 221 | ||
233 | dlm_release_lockspace(ls->dlm_lockspace, 2); | 222 | dlm_release_lockspace(ls->dlm_lockspace, 2); |
234 | gdlm_release_threads(ls); | 223 | gdlm_release_threads(ls); |
235 | gdlm_release_all_locks(ls); | ||
236 | gdlm_kobject_release(ls); | 224 | gdlm_kobject_release(ls); |
237 | } | 225 | } |
238 | 226 | ||
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c index a4ff271df9ee..4ec571c3d8a9 100644 --- a/fs/gfs2/locking/dlm/sysfs.c +++ b/fs/gfs2/locking/dlm/sysfs.c | |||
@@ -114,17 +114,6 @@ static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf) | |||
114 | return sprintf(buf, "%d\n", ls->recover_jid_status); | 114 | return sprintf(buf, "%d\n", ls->recover_jid_status); |
115 | } | 115 | } |
116 | 116 | ||
117 | static ssize_t drop_count_show(struct gdlm_ls *ls, char *buf) | ||
118 | { | ||
119 | return sprintf(buf, "%d\n", ls->drop_locks_count); | ||
120 | } | ||
121 | |||
122 | static ssize_t drop_count_store(struct gdlm_ls *ls, const char *buf, size_t len) | ||
123 | { | ||
124 | ls->drop_locks_count = simple_strtol(buf, NULL, 0); | ||
125 | return len; | ||
126 | } | ||
127 | |||
128 | struct gdlm_attr { | 117 | struct gdlm_attr { |
129 | struct attribute attr; | 118 | struct attribute attr; |
130 | ssize_t (*show)(struct gdlm_ls *, char *); | 119 | ssize_t (*show)(struct gdlm_ls *, char *); |
@@ -144,7 +133,6 @@ GDLM_ATTR(first_done, 0444, first_done_show, NULL); | |||
144 | GDLM_ATTR(recover, 0644, recover_show, recover_store); | 133 | GDLM_ATTR(recover, 0644, recover_show, recover_store); |
145 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); | 134 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); |
146 | GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); | 135 | GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); |
147 | GDLM_ATTR(drop_count, 0644, drop_count_show, drop_count_store); | ||
148 | 136 | ||
149 | static struct attribute *gdlm_attrs[] = { | 137 | static struct attribute *gdlm_attrs[] = { |
150 | &gdlm_attr_proto_name.attr, | 138 | &gdlm_attr_proto_name.attr, |
@@ -157,7 +145,6 @@ static struct attribute *gdlm_attrs[] = { | |||
157 | &gdlm_attr_recover.attr, | 145 | &gdlm_attr_recover.attr, |
158 | &gdlm_attr_recover_done.attr, | 146 | &gdlm_attr_recover_done.attr, |
159 | &gdlm_attr_recover_status.attr, | 147 | &gdlm_attr_recover_status.attr, |
160 | &gdlm_attr_drop_count.attr, | ||
161 | NULL, | 148 | NULL, |
162 | }; | 149 | }; |
163 | 150 | ||
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c index e53db6fd28ab..38823efd698c 100644 --- a/fs/gfs2/locking/dlm/thread.c +++ b/fs/gfs2/locking/dlm/thread.c | |||
@@ -9,367 +9,60 @@ | |||
9 | 9 | ||
10 | #include "lock_dlm.h" | 10 | #include "lock_dlm.h" |
11 | 11 | ||
12 | /* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm | 12 | static inline int no_work(struct gdlm_ls *ls) |
13 | thread gets to it. */ | ||
14 | |||
15 | static void queue_submit(struct gdlm_lock *lp) | ||
16 | { | ||
17 | struct gdlm_ls *ls = lp->ls; | ||
18 | |||
19 | spin_lock(&ls->async_lock); | ||
20 | list_add_tail(&lp->delay_list, &ls->submit); | ||
21 | spin_unlock(&ls->async_lock); | ||
22 | wake_up(&ls->thread_wait); | ||
23 | } | ||
24 | |||
25 | static void process_blocking(struct gdlm_lock *lp, int bast_mode) | ||
26 | { | ||
27 | struct gdlm_ls *ls = lp->ls; | ||
28 | unsigned int cb = 0; | ||
29 | |||
30 | switch (gdlm_make_lmstate(bast_mode)) { | ||
31 | case LM_ST_EXCLUSIVE: | ||
32 | cb = LM_CB_NEED_E; | ||
33 | break; | ||
34 | case LM_ST_DEFERRED: | ||
35 | cb = LM_CB_NEED_D; | ||
36 | break; | ||
37 | case LM_ST_SHARED: | ||
38 | cb = LM_CB_NEED_S; | ||
39 | break; | ||
40 | default: | ||
41 | gdlm_assert(0, "unknown bast mode %u", lp->bast_mode); | ||
42 | } | ||
43 | |||
44 | ls->fscb(ls->sdp, cb, &lp->lockname); | ||
45 | } | ||
46 | |||
47 | static void wake_up_ast(struct gdlm_lock *lp) | ||
48 | { | ||
49 | clear_bit(LFL_AST_WAIT, &lp->flags); | ||
50 | smp_mb__after_clear_bit(); | ||
51 | wake_up_bit(&lp->flags, LFL_AST_WAIT); | ||
52 | } | ||
53 | |||
54 | static void process_complete(struct gdlm_lock *lp) | ||
55 | { | ||
56 | struct gdlm_ls *ls = lp->ls; | ||
57 | struct lm_async_cb acb; | ||
58 | s16 prev_mode = lp->cur; | ||
59 | |||
60 | memset(&acb, 0, sizeof(acb)); | ||
61 | |||
62 | if (lp->lksb.sb_status == -DLM_ECANCEL) { | ||
63 | log_info("complete dlm cancel %x,%llx flags %lx", | ||
64 | lp->lockname.ln_type, | ||
65 | (unsigned long long)lp->lockname.ln_number, | ||
66 | lp->flags); | ||
67 | |||
68 | lp->req = lp->cur; | ||
69 | acb.lc_ret |= LM_OUT_CANCELED; | ||
70 | if (lp->cur == DLM_LOCK_IV) | ||
71 | lp->lksb.sb_lkid = 0; | ||
72 | goto out; | ||
73 | } | ||
74 | |||
75 | if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) { | ||
76 | if (lp->lksb.sb_status != -DLM_EUNLOCK) { | ||
77 | log_info("unlock sb_status %d %x,%llx flags %lx", | ||
78 | lp->lksb.sb_status, lp->lockname.ln_type, | ||
79 | (unsigned long long)lp->lockname.ln_number, | ||
80 | lp->flags); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | lp->cur = DLM_LOCK_IV; | ||
85 | lp->req = DLM_LOCK_IV; | ||
86 | lp->lksb.sb_lkid = 0; | ||
87 | |||
88 | if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) { | ||
89 | gdlm_delete_lp(lp); | ||
90 | return; | ||
91 | } | ||
92 | goto out; | ||
93 | } | ||
94 | |||
95 | if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID) | ||
96 | memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE); | ||
97 | |||
98 | if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) { | ||
99 | if (lp->req == DLM_LOCK_PR) | ||
100 | lp->req = DLM_LOCK_CW; | ||
101 | else if (lp->req == DLM_LOCK_CW) | ||
102 | lp->req = DLM_LOCK_PR; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * A canceled lock request. The lock was just taken off the delayed | ||
107 | * list and was never even submitted to dlm. | ||
108 | */ | ||
109 | |||
110 | if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) { | ||
111 | log_info("complete internal cancel %x,%llx", | ||
112 | lp->lockname.ln_type, | ||
113 | (unsigned long long)lp->lockname.ln_number); | ||
114 | lp->req = lp->cur; | ||
115 | acb.lc_ret |= LM_OUT_CANCELED; | ||
116 | goto out; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * An error occured. | ||
121 | */ | ||
122 | |||
123 | if (lp->lksb.sb_status) { | ||
124 | /* a "normal" error */ | ||
125 | if ((lp->lksb.sb_status == -EAGAIN) && | ||
126 | (lp->lkf & DLM_LKF_NOQUEUE)) { | ||
127 | lp->req = lp->cur; | ||
128 | if (lp->cur == DLM_LOCK_IV) | ||
129 | lp->lksb.sb_lkid = 0; | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* this could only happen with cancels I think */ | ||
134 | log_info("ast sb_status %d %x,%llx flags %lx", | ||
135 | lp->lksb.sb_status, lp->lockname.ln_type, | ||
136 | (unsigned long long)lp->lockname.ln_number, | ||
137 | lp->flags); | ||
138 | if (lp->lksb.sb_status == -EDEADLOCK && | ||
139 | lp->ls->fsflags & LM_MFLAG_CONV_NODROP) { | ||
140 | lp->req = lp->cur; | ||
141 | acb.lc_ret |= LM_OUT_CONV_DEADLK; | ||
142 | if (lp->cur == DLM_LOCK_IV) | ||
143 | lp->lksb.sb_lkid = 0; | ||
144 | goto out; | ||
145 | } else | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * This is an AST for an EX->EX conversion for sync_lvb from GFS. | ||
151 | */ | ||
152 | |||
153 | if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { | ||
154 | wake_up_ast(lp); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * A lock has been demoted to NL because it initially completed during | ||
160 | * BLOCK_LOCKS. Now it must be requested in the originally requested | ||
161 | * mode. | ||
162 | */ | ||
163 | |||
164 | if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) { | ||
165 | gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx", | ||
166 | lp->lockname.ln_type, | ||
167 | (unsigned long long)lp->lockname.ln_number); | ||
168 | gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx", | ||
169 | lp->lockname.ln_type, | ||
170 | (unsigned long long)lp->lockname.ln_number); | ||
171 | |||
172 | lp->cur = DLM_LOCK_NL; | ||
173 | lp->req = lp->prev_req; | ||
174 | lp->prev_req = DLM_LOCK_IV; | ||
175 | lp->lkf &= ~DLM_LKF_CONVDEADLK; | ||
176 | |||
177 | set_bit(LFL_NOCACHE, &lp->flags); | ||
178 | |||
179 | if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && | ||
180 | !test_bit(LFL_NOBLOCK, &lp->flags)) | ||
181 | gdlm_queue_delayed(lp); | ||
182 | else | ||
183 | queue_submit(lp); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * A request is granted during dlm recovery. It may be granted | ||
189 | * because the locks of a failed node were cleared. In that case, | ||
190 | * there may be inconsistent data beneath this lock and we must wait | ||
191 | * for recovery to complete to use it. When gfs recovery is done this | ||
192 | * granted lock will be converted to NL and then reacquired in this | ||
193 | * granted state. | ||
194 | */ | ||
195 | |||
196 | if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && | ||
197 | !test_bit(LFL_NOBLOCK, &lp->flags) && | ||
198 | lp->req != DLM_LOCK_NL) { | ||
199 | |||
200 | lp->cur = lp->req; | ||
201 | lp->prev_req = lp->req; | ||
202 | lp->req = DLM_LOCK_NL; | ||
203 | lp->lkf |= DLM_LKF_CONVERT; | ||
204 | lp->lkf &= ~DLM_LKF_CONVDEADLK; | ||
205 | |||
206 | log_debug("rereq %x,%llx id %x %d,%d", | ||
207 | lp->lockname.ln_type, | ||
208 | (unsigned long long)lp->lockname.ln_number, | ||
209 | lp->lksb.sb_lkid, lp->cur, lp->req); | ||
210 | |||
211 | set_bit(LFL_REREQUEST, &lp->flags); | ||
212 | queue_submit(lp); | ||
213 | return; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * DLM demoted the lock to NL before it was granted so GFS must be | ||
218 | * told it cannot cache data for this lock. | ||
219 | */ | ||
220 | |||
221 | if (lp->lksb.sb_flags & DLM_SBF_DEMOTED) | ||
222 | set_bit(LFL_NOCACHE, &lp->flags); | ||
223 | |||
224 | out: | ||
225 | /* | ||
226 | * This is an internal lock_dlm lock | ||
227 | */ | ||
228 | |||
229 | if (test_bit(LFL_INLOCK, &lp->flags)) { | ||
230 | clear_bit(LFL_NOBLOCK, &lp->flags); | ||
231 | lp->cur = lp->req; | ||
232 | wake_up_ast(lp); | ||
233 | return; | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * Normal completion of a lock request. Tell GFS it now has the lock. | ||
238 | */ | ||
239 | |||
240 | clear_bit(LFL_NOBLOCK, &lp->flags); | ||
241 | lp->cur = lp->req; | ||
242 | |||
243 | acb.lc_name = lp->lockname; | ||
244 | acb.lc_ret |= gdlm_make_lmstate(lp->cur); | ||
245 | |||
246 | if (!test_and_clear_bit(LFL_NOCACHE, &lp->flags) && | ||
247 | (lp->cur > DLM_LOCK_NL) && (prev_mode > DLM_LOCK_NL)) | ||
248 | acb.lc_ret |= LM_OUT_CACHEABLE; | ||
249 | |||
250 | ls->fscb(ls->sdp, LM_CB_ASYNC, &acb); | ||
251 | } | ||
252 | |||
253 | static inline int no_work(struct gdlm_ls *ls, int blocking) | ||
254 | { | 13 | { |
255 | int ret; | 14 | int ret; |
256 | 15 | ||
257 | spin_lock(&ls->async_lock); | 16 | spin_lock(&ls->async_lock); |
258 | ret = list_empty(&ls->complete) && list_empty(&ls->submit); | 17 | ret = list_empty(&ls->submit); |
259 | if (ret && blocking) | ||
260 | ret = list_empty(&ls->blocking); | ||
261 | spin_unlock(&ls->async_lock); | 18 | spin_unlock(&ls->async_lock); |
262 | 19 | ||
263 | return ret; | 20 | return ret; |
264 | } | 21 | } |
265 | 22 | ||
266 | static inline int check_drop(struct gdlm_ls *ls) | 23 | static int gdlm_thread(void *data) |
267 | { | ||
268 | if (!ls->drop_locks_count) | ||
269 | return 0; | ||
270 | |||
271 | if (time_after(jiffies, ls->drop_time + ls->drop_locks_period * HZ)) { | ||
272 | ls->drop_time = jiffies; | ||
273 | if (ls->all_locks_count >= ls->drop_locks_count) | ||
274 | return 1; | ||
275 | } | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int gdlm_thread(void *data, int blist) | ||
280 | { | 24 | { |
281 | struct gdlm_ls *ls = (struct gdlm_ls *) data; | 25 | struct gdlm_ls *ls = (struct gdlm_ls *) data; |
282 | struct gdlm_lock *lp = NULL; | 26 | struct gdlm_lock *lp = NULL; |
283 | uint8_t complete, blocking, submit, drop; | ||
284 | |||
285 | /* Only thread1 is allowed to do blocking callbacks since gfs | ||
286 | may wait for a completion callback within a blocking cb. */ | ||
287 | 27 | ||
288 | while (!kthread_should_stop()) { | 28 | while (!kthread_should_stop()) { |
289 | wait_event_interruptible(ls->thread_wait, | 29 | wait_event_interruptible(ls->thread_wait, |
290 | !no_work(ls, blist) || kthread_should_stop()); | 30 | !no_work(ls) || kthread_should_stop()); |
291 | |||
292 | complete = blocking = submit = drop = 0; | ||
293 | 31 | ||
294 | spin_lock(&ls->async_lock); | 32 | spin_lock(&ls->async_lock); |
295 | 33 | ||
296 | if (blist && !list_empty(&ls->blocking)) { | 34 | if (!list_empty(&ls->submit)) { |
297 | lp = list_entry(ls->blocking.next, struct gdlm_lock, | ||
298 | blist); | ||
299 | list_del_init(&lp->blist); | ||
300 | blocking = lp->bast_mode; | ||
301 | lp->bast_mode = 0; | ||
302 | } else if (!list_empty(&ls->complete)) { | ||
303 | lp = list_entry(ls->complete.next, struct gdlm_lock, | ||
304 | clist); | ||
305 | list_del_init(&lp->clist); | ||
306 | complete = 1; | ||
307 | } else if (!list_empty(&ls->submit)) { | ||
308 | lp = list_entry(ls->submit.next, struct gdlm_lock, | 35 | lp = list_entry(ls->submit.next, struct gdlm_lock, |
309 | delay_list); | 36 | delay_list); |
310 | list_del_init(&lp->delay_list); | 37 | list_del_init(&lp->delay_list); |
311 | submit = 1; | 38 | spin_unlock(&ls->async_lock); |
39 | gdlm_do_lock(lp); | ||
40 | spin_lock(&ls->async_lock); | ||
312 | } | 41 | } |
313 | |||
314 | drop = check_drop(ls); | ||
315 | spin_unlock(&ls->async_lock); | 42 | spin_unlock(&ls->async_lock); |
316 | |||
317 | if (complete) | ||
318 | process_complete(lp); | ||
319 | |||
320 | else if (blocking) | ||
321 | process_blocking(lp, blocking); | ||
322 | |||
323 | else if (submit) | ||
324 | gdlm_do_lock(lp); | ||
325 | |||
326 | if (drop) | ||
327 | ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL); | ||
328 | |||
329 | schedule(); | ||
330 | } | 43 | } |
331 | 44 | ||
332 | return 0; | 45 | return 0; |
333 | } | 46 | } |
334 | 47 | ||
335 | static int gdlm_thread1(void *data) | ||
336 | { | ||
337 | return gdlm_thread(data, 1); | ||
338 | } | ||
339 | |||
340 | static int gdlm_thread2(void *data) | ||
341 | { | ||
342 | return gdlm_thread(data, 0); | ||
343 | } | ||
344 | |||
345 | int gdlm_init_threads(struct gdlm_ls *ls) | 48 | int gdlm_init_threads(struct gdlm_ls *ls) |
346 | { | 49 | { |
347 | struct task_struct *p; | 50 | struct task_struct *p; |
348 | int error; | 51 | int error; |
349 | 52 | ||
350 | p = kthread_run(gdlm_thread1, ls, "lock_dlm1"); | 53 | p = kthread_run(gdlm_thread, ls, "lock_dlm"); |
351 | error = IS_ERR(p); | ||
352 | if (error) { | ||
353 | log_error("can't start lock_dlm1 thread %d", error); | ||
354 | return error; | ||
355 | } | ||
356 | ls->thread1 = p; | ||
357 | |||
358 | p = kthread_run(gdlm_thread2, ls, "lock_dlm2"); | ||
359 | error = IS_ERR(p); | 54 | error = IS_ERR(p); |
360 | if (error) { | 55 | if (error) { |
361 | log_error("can't start lock_dlm2 thread %d", error); | 56 | log_error("can't start lock_dlm thread %d", error); |
362 | kthread_stop(ls->thread1); | ||
363 | return error; | 57 | return error; |
364 | } | 58 | } |
365 | ls->thread2 = p; | 59 | ls->thread = p; |
366 | 60 | ||
367 | return 0; | 61 | return 0; |
368 | } | 62 | } |
369 | 63 | ||
370 | void gdlm_release_threads(struct gdlm_ls *ls) | 64 | void gdlm_release_threads(struct gdlm_ls *ls) |
371 | { | 65 | { |
372 | kthread_stop(ls->thread1); | 66 | kthread_stop(ls->thread); |
373 | kthread_stop(ls->thread2); | ||
374 | } | 67 | } |
375 | 68 | ||
diff --git a/fs/gfs2/locking/nolock/Makefile b/fs/gfs2/locking/nolock/Makefile deleted file mode 100644 index 35e9730bc3a8..000000000000 --- a/fs/gfs2/locking/nolock/Makefile +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += lock_nolock.o | ||
2 | lock_nolock-y := main.o | ||
3 | |||
diff --git a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c deleted file mode 100644 index 284a5ece8d94..000000000000 --- a/fs/gfs2/locking/nolock/main.c +++ /dev/null | |||
@@ -1,238 +0,0 @@ | |||
1 | /* | ||
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 | ||
7 | * of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/lm_interface.h> | ||
16 | |||
17 | struct nolock_lockspace { | ||
18 | unsigned int nl_lvb_size; | ||
19 | }; | ||
20 | |||
21 | static const struct lm_lockops nolock_ops; | ||
22 | |||
23 | static int nolock_mount(char *table_name, char *host_data, | ||
24 | lm_callback_t cb, void *cb_data, | ||
25 | unsigned int min_lvb_size, int flags, | ||
26 | struct lm_lockstruct *lockstruct, | ||
27 | struct kobject *fskobj) | ||
28 | { | ||
29 | char *c; | ||
30 | unsigned int jid; | ||
31 | struct nolock_lockspace *nl; | ||
32 | |||
33 | c = strstr(host_data, "jid="); | ||
34 | if (!c) | ||
35 | jid = 0; | ||
36 | else { | ||
37 | c += 4; | ||
38 | sscanf(c, "%u", &jid); | ||
39 | } | ||
40 | |||
41 | nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL); | ||
42 | if (!nl) | ||
43 | return -ENOMEM; | ||
44 | |||
45 | nl->nl_lvb_size = min_lvb_size; | ||
46 | |||
47 | lockstruct->ls_jid = jid; | ||
48 | lockstruct->ls_first = 1; | ||
49 | lockstruct->ls_lvb_size = min_lvb_size; | ||
50 | lockstruct->ls_lockspace = nl; | ||
51 | lockstruct->ls_ops = &nolock_ops; | ||
52 | lockstruct->ls_flags = LM_LSFLAG_LOCAL; | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void nolock_others_may_mount(void *lockspace) | ||
58 | { | ||
59 | } | ||
60 | |||
61 | static void nolock_unmount(void *lockspace) | ||
62 | { | ||
63 | struct nolock_lockspace *nl = lockspace; | ||
64 | kfree(nl); | ||
65 | } | ||
66 | |||
67 | static void nolock_withdraw(void *lockspace) | ||
68 | { | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * nolock_get_lock - get a lm_lock_t given a descripton of the lock | ||
73 | * @lockspace: the lockspace the lock lives in | ||
74 | * @name: the name of the lock | ||
75 | * @lockp: return the lm_lock_t here | ||
76 | * | ||
77 | * Returns: 0 on success, -EXXX on failure | ||
78 | */ | ||
79 | |||
80 | static int nolock_get_lock(void *lockspace, struct lm_lockname *name, | ||
81 | void **lockp) | ||
82 | { | ||
83 | *lockp = lockspace; | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * nolock_put_lock - get rid of a lock structure | ||
89 | * @lock: the lock to throw away | ||
90 | * | ||
91 | */ | ||
92 | |||
93 | static void nolock_put_lock(void *lock) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * nolock_lock - acquire a lock | ||
99 | * @lock: the lock to manipulate | ||
100 | * @cur_state: the current state | ||
101 | * @req_state: the requested state | ||
102 | * @flags: modifier flags | ||
103 | * | ||
104 | * Returns: A bitmap of LM_OUT_* | ||
105 | */ | ||
106 | |||
107 | static unsigned int nolock_lock(void *lock, unsigned int cur_state, | ||
108 | unsigned int req_state, unsigned int flags) | ||
109 | { | ||
110 | return req_state | LM_OUT_CACHEABLE; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * nolock_unlock - unlock a lock | ||
115 | * @lock: the lock to manipulate | ||
116 | * @cur_state: the current state | ||
117 | * | ||
118 | * Returns: 0 | ||
119 | */ | ||
120 | |||
121 | static unsigned int nolock_unlock(void *lock, unsigned int cur_state) | ||
122 | { | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static void nolock_cancel(void *lock) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * nolock_hold_lvb - hold on to a lock value block | ||
132 | * @lock: the lock the LVB is associated with | ||
133 | * @lvbp: return the lm_lvb_t here | ||
134 | * | ||
135 | * Returns: 0 on success, -EXXX on failure | ||
136 | */ | ||
137 | |||
138 | static int nolock_hold_lvb(void *lock, char **lvbp) | ||
139 | { | ||
140 | struct nolock_lockspace *nl = lock; | ||
141 | int error = 0; | ||
142 | |||
143 | *lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS); | ||
144 | if (!*lvbp) | ||
145 | error = -ENOMEM; | ||
146 | |||
147 | return error; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * nolock_unhold_lvb - release a LVB | ||
152 | * @lock: the lock the LVB is associated with | ||
153 | * @lvb: the lock value block | ||
154 | * | ||
155 | */ | ||
156 | |||
157 | static void nolock_unhold_lvb(void *lock, char *lvb) | ||
158 | { | ||
159 | kfree(lvb); | ||
160 | } | ||
161 | |||
162 | static int nolock_plock_get(void *lockspace, struct lm_lockname *name, | ||
163 | struct file *file, struct file_lock *fl) | ||
164 | { | ||
165 | posix_test_lock(file, fl); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int nolock_plock(void *lockspace, struct lm_lockname *name, | ||
171 | struct file *file, int cmd, struct file_lock *fl) | ||
172 | { | ||
173 | int error; | ||
174 | error = posix_lock_file_wait(file, fl); | ||
175 | return error; | ||
176 | } | ||
177 | |||
178 | static int nolock_punlock(void *lockspace, struct lm_lockname *name, | ||
179 | struct file *file, struct file_lock *fl) | ||
180 | { | ||
181 | int error; | ||
182 | error = posix_lock_file_wait(file, fl); | ||
183 | return error; | ||
184 | } | ||
185 | |||
186 | static void nolock_recovery_done(void *lockspace, unsigned int jid, | ||
187 | unsigned int message) | ||
188 | { | ||
189 | } | ||
190 | |||
191 | static const struct lm_lockops nolock_ops = { | ||
192 | .lm_proto_name = "lock_nolock", | ||
193 | .lm_mount = nolock_mount, | ||
194 | .lm_others_may_mount = nolock_others_may_mount, | ||
195 | .lm_unmount = nolock_unmount, | ||
196 | .lm_withdraw = nolock_withdraw, | ||
197 | .lm_get_lock = nolock_get_lock, | ||
198 | .lm_put_lock = nolock_put_lock, | ||
199 | .lm_lock = nolock_lock, | ||
200 | .lm_unlock = nolock_unlock, | ||
201 | .lm_cancel = nolock_cancel, | ||
202 | .lm_hold_lvb = nolock_hold_lvb, | ||
203 | .lm_unhold_lvb = nolock_unhold_lvb, | ||
204 | .lm_plock_get = nolock_plock_get, | ||
205 | .lm_plock = nolock_plock, | ||
206 | .lm_punlock = nolock_punlock, | ||
207 | .lm_recovery_done = nolock_recovery_done, | ||
208 | .lm_owner = THIS_MODULE, | ||
209 | }; | ||
210 | |||
211 | static int __init init_nolock(void) | ||
212 | { | ||
213 | int error; | ||
214 | |||
215 | error = gfs2_register_lockproto(&nolock_ops); | ||
216 | if (error) { | ||
217 | printk(KERN_WARNING | ||
218 | "lock_nolock: can't register protocol: %d\n", error); | ||
219 | return error; | ||
220 | } | ||
221 | |||
222 | printk(KERN_INFO | ||
223 | "Lock_Nolock (built %s %s) installed\n", __DATE__, __TIME__); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static void __exit exit_nolock(void) | ||
228 | { | ||
229 | gfs2_unregister_lockproto(&nolock_ops); | ||
230 | } | ||
231 | |||
232 | module_init(init_nolock); | ||
233 | module_exit(exit_nolock); | ||
234 | |||
235 | MODULE_DESCRIPTION("GFS Nolock Locking Module"); | ||
236 | MODULE_AUTHOR("Red Hat, Inc."); | ||
237 | MODULE_LICENSE("GPL"); | ||
238 | |||