Blame view

fs/ocfs2/dlm/dlmthread.c 20.6 KB
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  /* -*- mode: c; c-basic-offset: 8; -*-
   * vim: noexpandtab sw=8 ts=8 sts=0:
   *
   * dlmthread.c
   *
   * standalone DLM module
   *
   * Copyright (C) 2004 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License as published by the Free Software Foundation; either
   * version 2 of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   *
   */
  
  
  #include <linux/module.h>
  #include <linux/fs.h>
  #include <linux/types.h>
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
31
  #include <linux/highmem.h>
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
32
33
34
35
36
37
38
39
  #include <linux/init.h>
  #include <linux/sysctl.h>
  #include <linux/random.h>
  #include <linux/blkdev.h>
  #include <linux/socket.h>
  #include <linux/inet.h>
  #include <linux/timer.h>
  #include <linux/kthread.h>
8d79d088e   Kurt Hackel   ocfs2: add a smal...
40
  #include <linux/delay.h>
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
41
42
43
44
45
46
47
48
49
50
51
52
  
  
  #include "cluster/heartbeat.h"
  #include "cluster/nodemanager.h"
  #include "cluster/tcp.h"
  
  #include "dlmapi.h"
  #include "dlmcommon.h"
  #include "dlmdomain.h"
  
  #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_THREAD)
  #include "cluster/masklog.h"
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
53
  static int dlm_thread(void *data);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  static void dlm_flush_asts(struct dlm_ctxt *dlm);
  
  #define dlm_lock_is_remote(dlm, lock)     ((lock)->ml.node != (dlm)->node_num)
  
  /* will exit holding res->spinlock, but may drop in function */
  /* waits until flags are cleared on res->state */
  void __dlm_wait_on_lockres_flags(struct dlm_lock_resource *res, int flags)
  {
  	DECLARE_WAITQUEUE(wait, current);
  
  	assert_spin_locked(&res->spinlock);
  
  	add_wait_queue(&res->wq, &wait);
  repeat:
  	set_current_state(TASK_UNINTERRUPTIBLE);
  	if (res->state & flags) {
  		spin_unlock(&res->spinlock);
  		schedule();
  		spin_lock(&res->spinlock);
  		goto repeat;
  	}
  	remove_wait_queue(&res->wq, &wait);
5c2c9d383   Milind Arun Choudhary   [PATCH] ocfs2: us...
76
  	__set_current_state(TASK_RUNNING);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
77
  }
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
78
  int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
79
80
81
  {
  	if (list_empty(&res->granted) &&
  	    list_empty(&res->converting) &&
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
82
83
84
85
86
87
88
89
90
91
92
  	    list_empty(&res->blocked))
  		return 0;
  	return 1;
  }
  
  /* "unused": the lockres has no locks, is not on the dirty list,
   * has no inflight locks (in the gap between mastery and acquiring
   * the first lock), and has no bits in its refmap.
   * truly ready to be freed. */
  int __dlm_lockres_unused(struct dlm_lock_resource *res)
  {
a524812b7   Wengang Wang   ocfs2/dlm: avoid ...
93
  	int bit;
ff0a522e7   Sunil Mushran   ocfs2/dlm: Take i...
94
  	assert_spin_locked(&res->spinlock);
a524812b7   Wengang Wang   ocfs2/dlm: avoid ...
95
96
  	if (__dlm_lockres_has_locks(res))
  		return 0;
ff0a522e7   Sunil Mushran   ocfs2/dlm: Take i...
97
98
99
  	/* Locks are in the process of being created */
  	if (res->inflight_locks)
  		return 0;
a524812b7   Wengang Wang   ocfs2/dlm: avoid ...
100
101
102
103
104
  	if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
  		return 0;
  
  	if (res->state & DLM_LOCK_RES_RECOVERING)
  		return 0;
ff0a522e7   Sunil Mushran   ocfs2/dlm: Take i...
105
  	/* Another node has this resource with this node as the master */
a524812b7   Wengang Wang   ocfs2/dlm: avoid ...
106
107
108
  	bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
  	if (bit < O2NM_MAX_NODES)
  		return 0;
a524812b7   Wengang Wang   ocfs2/dlm: avoid ...
109
  	return 1;
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
110
111
112
113
114
115
116
117
118
  }
  
  
  /* Call whenever you may have added or deleted something from one of
   * the lockres queue's. This will figure out whether it belongs on the
   * unused list or not and does the appropriate thing. */
  void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
  			      struct dlm_lock_resource *res)
  {
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
119
120
121
122
123
  	assert_spin_locked(&dlm->spinlock);
  	assert_spin_locked(&res->spinlock);
  
  	if (__dlm_lockres_unused(res)){
  		if (list_empty(&res->purge)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
124
125
126
  			mlog(0, "%s: Adding res %.*s to purge list
  ",
  			     dlm->name, res->lockname.len, res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
127
128
  
  			res->last_used = jiffies;
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
129
  			dlm_lockres_get(res);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
130
131
132
133
  			list_add_tail(&res->purge, &dlm->purge_list);
  			dlm->purge_count++;
  		}
  	} else if (!list_empty(&res->purge)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
134
135
136
  		mlog(0, "%s: Removing res %.*s from purge list
  ",
  		     dlm->name, res->lockname.len, res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
137
138
  
  		list_del_init(&res->purge);
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
139
  		dlm_lockres_put(res);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
140
141
142
143
144
145
146
  		dlm->purge_count--;
  	}
  }
  
  void dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
  			    struct dlm_lock_resource *res)
  {
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
147
148
149
150
151
152
153
154
  	spin_lock(&dlm->spinlock);
  	spin_lock(&res->spinlock);
  
  	__dlm_lockres_calc_usage(dlm, res);
  
  	spin_unlock(&res->spinlock);
  	spin_unlock(&dlm->spinlock);
  }
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
155
  static void dlm_purge_lockres(struct dlm_ctxt *dlm,
faf0ec9f1   Adrian Bunk   [PATCH] fs/ocfs2/...
156
  			     struct dlm_lock_resource *res)
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
157
158
  {
  	int master;
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
159
  	int ret = 0;
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
160

7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
161
162
  	assert_spin_locked(&dlm->spinlock);
  	assert_spin_locked(&res->spinlock);
516b7e52a   Sunil Mushran   ocfs2/dlm: Do not...
163

ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
164
  	master = (res->owner == dlm->node_num);
516b7e52a   Sunil Mushran   ocfs2/dlm: Do not...
165

8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
166
167
168
  	mlog(0, "%s: Purging res %.*s, master %d
  ", dlm->name,
  	     res->lockname.len, res->lockname.name, master);
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
169
170
  
  	if (!master) {
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
171
  		res->state |= DLM_LOCK_RES_DROPPING_REF;
c824c3c72   Sunil Mushran   ocfs2/dlm: dlm_th...
172
  		/* drop spinlock...  retake below */
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
173
  		spin_unlock(&res->spinlock);
c824c3c72   Sunil Mushran   ocfs2/dlm: dlm_th...
174
  		spin_unlock(&dlm->spinlock);
3b8118cff   Kurt Hackel   ocfs2_dlm: Callin...
175
176
  		spin_lock(&res->spinlock);
  		/* This ensures that clear refmap is sent after the set */
7dc102b73   Sunil Mushran   ocfs2/dlm: Retrac...
177
  		__dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
3b8118cff   Kurt Hackel   ocfs2_dlm: Callin...
178
  		spin_unlock(&res->spinlock);
c824c3c72   Sunil Mushran   ocfs2/dlm: dlm_th...
179

ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
180
181
182
  		/* clear our bit from the master's refmap, ignore errors */
  		ret = dlm_drop_lockres_ref(dlm, res);
  		if (ret < 0) {
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
183
184
185
  			if (!dlm_is_host_down(ret))
  				BUG();
  		}
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
186
  		spin_lock(&dlm->spinlock);
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
187
  		spin_lock(&res->spinlock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
188
  	}
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
189
  	if (!list_empty(&res->purge)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
190
191
192
  		mlog(0, "%s: Removing res %.*s from purgelist, master %d
  ",
  		     dlm->name, res->lockname.len, res->lockname.name, master);
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
193
194
  		list_del_init(&res->purge);
  		dlm_lockres_put(res);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
195
  		dlm->purge_count--;
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
196
197
198
  	}
  
  	if (!__dlm_lockres_unused(res)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
199
200
  		mlog(ML_ERROR, "%s: res %.*s in use after deref
  ",
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
201
202
203
204
  		     dlm->name, res->lockname.len, res->lockname.name);
  		__dlm_print_one_lock_resource(res);
  		BUG();
  	}
83e32d904   Wengang Wang   ocfs2: add spinlo...
205

e9f0b6a62   Sunil Mushran   ocfs2/dlm: Trace ...
206
  	__dlm_unhash_lockres(dlm, res);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
207

ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
208
209
210
  	/* lockres is not in the hash now.  drop the flag and wake up
  	 * any processes waiting in dlm_get_lock_resource. */
  	if (!master) {
ba2bf2185   Kurt Hackel   ocfs2_dlm: fix cl...
211
212
213
  		res->state &= ~DLM_LOCK_RES_DROPPING_REF;
  		spin_unlock(&res->spinlock);
  		wake_up(&res->wq);
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
214
215
  	} else
  		spin_unlock(&res->spinlock);
8b2198097   Kurt Hackel   ocfs2: purge lock...
216
  }
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  static void dlm_run_purge_list(struct dlm_ctxt *dlm,
  			       int purge_now)
  {
  	unsigned int run_max, unused;
  	unsigned long purge_jiffies;
  	struct dlm_lock_resource *lockres;
  
  	spin_lock(&dlm->spinlock);
  	run_max = dlm->purge_count;
  
  	while(run_max && !list_empty(&dlm->purge_list)) {
  		run_max--;
  
  		lockres = list_entry(dlm->purge_list.next,
  				     struct dlm_lock_resource, purge);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
232
  		spin_lock(&lockres->spinlock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
233
234
235
236
237
238
239
240
241
242
243
  
  		purge_jiffies = lockres->last_used +
  			msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);
  
  		/* Make sure that we want to be processing this guy at
  		 * this time. */
  		if (!purge_now && time_after(purge_jiffies, jiffies)) {
  			/* Since resources are added to the purge list
  			 * in tail order, we can stop at the first
  			 * unpurgable resource -- anyone added after
  			 * him will have a greater last_used value */
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
244
  			spin_unlock(&lockres->spinlock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
245
246
  			break;
  		}
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
247
248
249
250
251
252
253
  		/* Status of the lockres *might* change so double
  		 * check. If the lockres is unused, holding the dlm
  		 * spinlock will prevent people from getting and more
  		 * refs on it. */
  		unused = __dlm_lockres_unused(lockres);
  		if (!unused ||
  		    (lockres->state & DLM_LOCK_RES_MIGRATING)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
254
255
256
257
258
  			mlog(0, "%s: res %.*s is in use or being remastered, "
  			     "used %d, state %d
  ", dlm->name,
  			     lockres->lockname.len, lockres->lockname.name,
  			     !unused, lockres->state);
7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
259
260
261
262
  			list_move_tail(&dlm->purge_list, &lockres->purge);
  			spin_unlock(&lockres->spinlock);
  			continue;
  		}
78062cb2e   Sunil Mushran   ocfs2_dlm: Fix lo...
263
  		dlm_lockres_get(lockres);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
264

7beaf2437   Srinivas Eeda   ocfs2 fix o2dlm d...
265
  		dlm_purge_lockres(dlm, lockres);
78062cb2e   Sunil Mushran   ocfs2_dlm: Fix lo...
266

3fca0894a   Sunil Mushran   ocfs2_dlm: Missin...
267
  		dlm_lockres_put(lockres);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  
  		/* Avoid adding any scheduling latencies */
  		cond_resched_lock(&dlm->spinlock);
  	}
  
  	spin_unlock(&dlm->spinlock);
  }
  
  static void dlm_shuffle_lists(struct dlm_ctxt *dlm,
  			      struct dlm_lock_resource *res)
  {
  	struct dlm_lock *lock, *target;
  	struct list_head *iter;
  	struct list_head *head;
  	int can_grant = 1;
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
283
284
  	/*
  	 * Because this function is called with the lockres
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
285
286
  	 * spinlock, and because we know that it is not migrating/
  	 * recovering/in-progress, it is fine to reserve asts and
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
287
288
  	 * basts right before queueing them all throughout
  	 */
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
289
  	assert_spin_locked(&dlm->ast_lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
290
291
292
293
294
295
296
297
  	assert_spin_locked(&res->spinlock);
  	BUG_ON((res->state & (DLM_LOCK_RES_MIGRATING|
  			      DLM_LOCK_RES_RECOVERING|
  			      DLM_LOCK_RES_IN_PROGRESS)));
  
  converting:
  	if (list_empty(&res->converting))
  		goto blocked;
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
298
299
300
  	mlog(0, "%s: res %.*s has locks on the convert queue
  ", dlm->name,
  	     res->lockname.len, res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
301
302
303
  
  	target = list_entry(res->converting.next, struct dlm_lock, list);
  	if (target->ml.convert_type == LKM_IVMODE) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
304
305
306
  		mlog(ML_ERROR, "%s: res %.*s converting lock to invalid mode
  ",
  		     dlm->name, res->lockname.len, res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
307
308
309
310
311
312
313
314
315
316
317
318
319
  		BUG();
  	}
  	head = &res->granted;
  	list_for_each(iter, head) {
  		lock = list_entry(iter, struct dlm_lock, list);
  		if (lock==target)
  			continue;
  		if (!dlm_lock_compatible(lock->ml.type,
  					 target->ml.convert_type)) {
  			can_grant = 0;
  			/* queue the BAST if not already */
  			if (lock->ml.highest_blocked == LKM_IVMODE) {
  				__dlm_lockres_reserve_ast(res);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
320
  				__dlm_queue_bast(dlm, lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  			}
  			/* update the highest_blocked if needed */
  			if (lock->ml.highest_blocked < target->ml.convert_type)
  				lock->ml.highest_blocked =
  					target->ml.convert_type;
  		}
  	}
  	head = &res->converting;
  	list_for_each(iter, head) {
  		lock = list_entry(iter, struct dlm_lock, list);
  		if (lock==target)
  			continue;
  		if (!dlm_lock_compatible(lock->ml.type,
  					 target->ml.convert_type)) {
  			can_grant = 0;
  			if (lock->ml.highest_blocked == LKM_IVMODE) {
  				__dlm_lockres_reserve_ast(res);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
338
  				__dlm_queue_bast(dlm, lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
339
340
341
342
343
344
345
346
347
348
349
  			}
  			if (lock->ml.highest_blocked < target->ml.convert_type)
  				lock->ml.highest_blocked =
  					target->ml.convert_type;
  		}
  	}
  
  	/* we can convert the lock */
  	if (can_grant) {
  		spin_lock(&target->spinlock);
  		BUG_ON(target->ml.highest_blocked != LKM_IVMODE);
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
350
351
352
353
354
355
356
  		mlog(0, "%s: res %.*s, AST for Converting lock %u:%llu, type "
  		     "%d => %d, node %u
  ", dlm->name, res->lockname.len,
  		     res->lockname.name,
  		     dlm_get_lock_cookie_node(be64_to_cpu(target->ml.cookie)),
  		     dlm_get_lock_cookie_seq(be64_to_cpu(target->ml.cookie)),
  		     target->ml.type,
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
357
358
359
360
  		     target->ml.convert_type, target->ml.node);
  
  		target->ml.type = target->ml.convert_type;
  		target->ml.convert_type = LKM_IVMODE;
f116629d0   Akinobu Mita   [PATCH] fs: use l...
361
  		list_move_tail(&target->list, &res->granted);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
362
363
364
365
366
367
368
  
  		BUG_ON(!target->lksb);
  		target->lksb->status = DLM_NORMAL;
  
  		spin_unlock(&target->spinlock);
  
  		__dlm_lockres_reserve_ast(res);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
369
  		__dlm_queue_ast(dlm, target);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  		/* go back and check for more */
  		goto converting;
  	}
  
  blocked:
  	if (list_empty(&res->blocked))
  		goto leave;
  	target = list_entry(res->blocked.next, struct dlm_lock, list);
  
  	head = &res->granted;
  	list_for_each(iter, head) {
  		lock = list_entry(iter, struct dlm_lock, list);
  		if (lock==target)
  			continue;
  		if (!dlm_lock_compatible(lock->ml.type, target->ml.type)) {
  			can_grant = 0;
  			if (lock->ml.highest_blocked == LKM_IVMODE) {
  				__dlm_lockres_reserve_ast(res);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
388
  				__dlm_queue_bast(dlm, lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  			}
  			if (lock->ml.highest_blocked < target->ml.type)
  				lock->ml.highest_blocked = target->ml.type;
  		}
  	}
  
  	head = &res->converting;
  	list_for_each(iter, head) {
  		lock = list_entry(iter, struct dlm_lock, list);
  		if (lock==target)
  			continue;
  		if (!dlm_lock_compatible(lock->ml.type, target->ml.type)) {
  			can_grant = 0;
  			if (lock->ml.highest_blocked == LKM_IVMODE) {
  				__dlm_lockres_reserve_ast(res);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
404
  				__dlm_queue_bast(dlm, lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
405
406
407
408
409
410
411
412
413
414
415
  			}
  			if (lock->ml.highest_blocked < target->ml.type)
  				lock->ml.highest_blocked = target->ml.type;
  		}
  	}
  
  	/* we can grant the blocked lock (only
  	 * possible if converting list empty) */
  	if (can_grant) {
  		spin_lock(&target->spinlock);
  		BUG_ON(target->ml.highest_blocked != LKM_IVMODE);
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
416
417
418
419
420
421
  		mlog(0, "%s: res %.*s, AST for Blocked lock %u:%llu, type %d, "
  		     "node %u
  ", dlm->name, res->lockname.len,
  		     res->lockname.name,
  		     dlm_get_lock_cookie_node(be64_to_cpu(target->ml.cookie)),
  		     dlm_get_lock_cookie_seq(be64_to_cpu(target->ml.cookie)),
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
422
  		     target->ml.type, target->ml.node);
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
423
  		/* target->ml.type is already correct */
f116629d0   Akinobu Mita   [PATCH] fs: use l...
424
  		list_move_tail(&target->list, &res->granted);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
425
426
427
428
429
430
431
  
  		BUG_ON(!target->lksb);
  		target->lksb->status = DLM_NORMAL;
  
  		spin_unlock(&target->spinlock);
  
  		__dlm_lockres_reserve_ast(res);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
432
  		__dlm_queue_ast(dlm, target);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
433
434
435
436
437
438
439
440
441
442
443
  		/* go back and check for more */
  		goto converting;
  	}
  
  leave:
  	return;
  }
  
  /* must have NO locks when calling this with res !=NULL * */
  void dlm_kick_thread(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
  {
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
444
445
446
447
448
449
450
451
452
453
454
455
  	if (res) {
  		spin_lock(&dlm->spinlock);
  		spin_lock(&res->spinlock);
  		__dlm_dirty_lockres(dlm, res);
  		spin_unlock(&res->spinlock);
  		spin_unlock(&dlm->spinlock);
  	}
  	wake_up(&dlm->dlm_thread_wq);
  }
  
  void __dlm_dirty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
  {
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
456
457
458
459
  	assert_spin_locked(&dlm->spinlock);
  	assert_spin_locked(&res->spinlock);
  
  	/* don't shuffle secondary queues */
ddc09c8dd   Kurt Hackel   ocfs2_dlm: Fixes ...
460
461
462
463
464
465
466
467
468
469
470
  	if ((res->owner == dlm->node_num)) {
  		if (res->state & (DLM_LOCK_RES_MIGRATING |
  				  DLM_LOCK_RES_BLOCK_DIRTY))
  		    return;
  
  		if (list_empty(&res->dirty)) {
  			/* ref for dirty_list */
  			dlm_lockres_get(res);
  			list_add_tail(&res->dirty, &dlm->dirty_list);
  			res->state |= DLM_LOCK_RES_DIRTY;
  		}
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
471
  	}
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
472
473
474
475
  
  	mlog(0, "%s: res %.*s
  ", dlm->name, res->lockname.len,
  	     res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
476
477
478
479
480
481
  }
  
  
  /* Launch the NM thread for the mounted volume */
  int dlm_launch_thread(struct dlm_ctxt *dlm)
  {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
482
483
  	mlog(0, "Starting dlm_thread...
  ");
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  
  	dlm->dlm_thread_task = kthread_run(dlm_thread, dlm, "dlm_thread");
  	if (IS_ERR(dlm->dlm_thread_task)) {
  		mlog_errno(PTR_ERR(dlm->dlm_thread_task));
  		dlm->dlm_thread_task = NULL;
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  void dlm_complete_thread(struct dlm_ctxt *dlm)
  {
  	if (dlm->dlm_thread_task) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
498
499
  		mlog(ML_KTHREAD, "Waiting for dlm thread to exit
  ");
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  		kthread_stop(dlm->dlm_thread_task);
  		dlm->dlm_thread_task = NULL;
  	}
  }
  
  static int dlm_dirty_list_empty(struct dlm_ctxt *dlm)
  {
  	int empty;
  
  	spin_lock(&dlm->spinlock);
  	empty = list_empty(&dlm->dirty_list);
  	spin_unlock(&dlm->spinlock);
  
  	return empty;
  }
  
  static void dlm_flush_asts(struct dlm_ctxt *dlm)
  {
  	int ret;
  	struct dlm_lock *lock;
  	struct dlm_lock_resource *res;
  	u8 hi;
  
  	spin_lock(&dlm->ast_lock);
  	while (!list_empty(&dlm->pending_asts)) {
  		lock = list_entry(dlm->pending_asts.next,
  				  struct dlm_lock, ast_list);
  		/* get an extra ref on lock */
  		dlm_lock_get(lock);
  		res = lock->lockres;
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
530
531
532
533
534
535
536
  		mlog(0, "%s: res %.*s, Flush AST for lock %u:%llu, type %d, "
  		     "node %u
  ", dlm->name, res->lockname.len,
  		     res->lockname.name,
  		     dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
  		     dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
  		     lock->ml.type, lock->ml.node);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
  
  		BUG_ON(!lock->ast_pending);
  
  		/* remove from list (including ref) */
  		list_del_init(&lock->ast_list);
  		dlm_lock_put(lock);
  		spin_unlock(&dlm->ast_lock);
  
  		if (lock->ml.node != dlm->node_num) {
  			ret = dlm_do_remote_ast(dlm, res, lock);
  			if (ret < 0)
  				mlog_errno(ret);
  		} else
  			dlm_do_local_ast(dlm, res, lock);
  
  		spin_lock(&dlm->ast_lock);
  
  		/* possible that another ast was queued while
  		 * we were delivering the last one */
  		if (!list_empty(&lock->ast_list)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
557
558
559
560
  			mlog(0, "%s: res %.*s, AST queued while flushing last "
  			     "one
  ", dlm->name, res->lockname.len,
  			     res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  		} else
  			lock->ast_pending = 0;
  
  		/* drop the extra ref.
  		 * this may drop it completely. */
  		dlm_lock_put(lock);
  		dlm_lockres_release_ast(dlm, res);
  	}
  
  	while (!list_empty(&dlm->pending_basts)) {
  		lock = list_entry(dlm->pending_basts.next,
  				  struct dlm_lock, bast_list);
  		/* get an extra ref on lock */
  		dlm_lock_get(lock);
  		res = lock->lockres;
  
  		BUG_ON(!lock->bast_pending);
  
  		/* get the highest blocked lock, and reset */
  		spin_lock(&lock->spinlock);
  		BUG_ON(lock->ml.highest_blocked <= LKM_IVMODE);
  		hi = lock->ml.highest_blocked;
  		lock->ml.highest_blocked = LKM_IVMODE;
  		spin_unlock(&lock->spinlock);
  
  		/* remove from list (including ref) */
  		list_del_init(&lock->bast_list);
  		dlm_lock_put(lock);
  		spin_unlock(&dlm->ast_lock);
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
590
591
592
593
594
595
596
  		mlog(0, "%s: res %.*s, Flush BAST for lock %u:%llu, "
  		     "blocked %d, node %u
  ",
  		     dlm->name, res->lockname.len, res->lockname.name,
  		     dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
  		     dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
  		     hi, lock->ml.node);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
597
598
599
600
601
602
603
604
605
606
607
608
609
  
  		if (lock->ml.node != dlm->node_num) {
  			ret = dlm_send_proxy_bast(dlm, res, lock, hi);
  			if (ret < 0)
  				mlog_errno(ret);
  		} else
  			dlm_do_local_bast(dlm, res, lock, hi);
  
  		spin_lock(&dlm->ast_lock);
  
  		/* possible that another bast was queued while
  		 * we were delivering the last one */
  		if (!list_empty(&lock->bast_list)) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
610
611
612
613
  			mlog(0, "%s: res %.*s, BAST queued while flushing last "
  			     "one
  ", dlm->name, res->lockname.len,
  			     res->lockname.name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
  		} else
  			lock->bast_pending = 0;
  
  		/* drop the extra ref.
  		 * this may drop it completely. */
  		dlm_lock_put(lock);
  		dlm_lockres_release_ast(dlm, res);
  	}
  	wake_up(&dlm->ast_wq);
  	spin_unlock(&dlm->ast_lock);
  }
  
  
  #define DLM_THREAD_TIMEOUT_MS (4 * 1000)
  #define DLM_THREAD_MAX_DIRTY  100
  #define DLM_THREAD_MAX_ASTS   10
  
  static int dlm_thread(void *data)
  {
  	struct dlm_lock_resource *res;
  	struct dlm_ctxt *dlm = data;
  	unsigned long timeout = msecs_to_jiffies(DLM_THREAD_TIMEOUT_MS);
  
  	mlog(0, "dlm thread running for %s...
  ", dlm->name);
  
  	while (!kthread_should_stop()) {
  		int n = DLM_THREAD_MAX_DIRTY;
  
  		/* dlm_shutting_down is very point-in-time, but that
  		 * doesn't matter as we'll just loop back around if we
  		 * get false on the leading edge of a state
  		 * transition. */
  		dlm_run_purge_list(dlm, dlm_shutting_down(dlm));
  
  		/* We really don't want to hold dlm->spinlock while
  		 * calling dlm_shuffle_lists on each lockres that
  		 * needs to have its queues adjusted and AST/BASTs
  		 * run.  So let's pull each entry off the dirty_list
  		 * and drop dlm->spinlock ASAP.  Once off the list,
  		 * res->spinlock needs to be taken again to protect
  		 * the queues while calling dlm_shuffle_lists.  */
  		spin_lock(&dlm->spinlock);
  		while (!list_empty(&dlm->dirty_list)) {
  			int delay = 0;
  			res = list_entry(dlm->dirty_list.next,
  					 struct dlm_lock_resource, dirty);
  
  			/* peel a lockres off, remove it from the list,
  			 * unset the dirty flag and drop the dlm lock */
  			BUG_ON(!res);
  			dlm_lockres_get(res);
  
  			spin_lock(&res->spinlock);
ddc09c8dd   Kurt Hackel   ocfs2_dlm: Fixes ...
668
  			/* We clear the DLM_LOCK_RES_DIRTY state once we shuffle lists below */
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
669
670
671
  			list_del_init(&res->dirty);
  			spin_unlock(&res->spinlock);
  			spin_unlock(&dlm->spinlock);
6ff06a939   Kurt Hackel   ocfs2: give the d...
672
673
  			/* Drop dirty_list ref */
  			dlm_lockres_put(res);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
674
675
676
  
  		 	/* lockres can be re-dirtied/re-added to the
  			 * dirty_list in this gap, but that is ok */
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
677
  			spin_lock(&dlm->ast_lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
678
679
680
  			spin_lock(&res->spinlock);
  			if (res->owner != dlm->node_num) {
  				__dlm_print_one_lock_resource(res);
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
681
682
683
684
685
686
687
  				mlog(ML_ERROR, "%s: inprog %d, mig %d, reco %d,"
  				     " dirty %d
  ", dlm->name,
  				     !!(res->state & DLM_LOCK_RES_IN_PROGRESS),
  				     !!(res->state & DLM_LOCK_RES_MIGRATING),
  				     !!(res->state & DLM_LOCK_RES_RECOVERING),
  				     !!(res->state & DLM_LOCK_RES_DIRTY));
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
688
689
690
691
692
693
  			}
  			BUG_ON(res->owner != dlm->node_num);
  
  			/* it is now ok to move lockreses in these states
  			 * to the dirty list, assuming that they will only be
  			 * dirty for a short while. */
ddc09c8dd   Kurt Hackel   ocfs2_dlm: Fixes ...
694
  			BUG_ON(res->state & DLM_LOCK_RES_MIGRATING);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
695
  			if (res->state & (DLM_LOCK_RES_IN_PROGRESS |
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
696
697
  					  DLM_LOCK_RES_RECOVERING)) {
  				/* move it to the tail and keep going */
ddc09c8dd   Kurt Hackel   ocfs2_dlm: Fixes ...
698
  				res->state &= ~DLM_LOCK_RES_DIRTY;
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
699
  				spin_unlock(&res->spinlock);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
700
  				spin_unlock(&dlm->ast_lock);
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
701
702
703
  				mlog(0, "%s: res %.*s, inprogress, delay list "
  				     "shuffle, state %d
  ", dlm->name,
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
704
705
706
707
708
709
710
711
712
713
  				     res->lockname.len, res->lockname.name,
  				     res->state);
  				delay = 1;
  				goto in_progress;
  			}
  
  			/* at this point the lockres is not migrating/
  			 * recovering/in-progress.  we have the lockres
  			 * spinlock and do NOT have the dlm lock.
  			 * safe to reserve/queue asts and run the lists. */
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
714
715
  			/* called while holding lockres lock */
  			dlm_shuffle_lists(dlm, res);
ddc09c8dd   Kurt Hackel   ocfs2_dlm: Fixes ...
716
  			res->state &= ~DLM_LOCK_RES_DIRTY;
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
717
  			spin_unlock(&res->spinlock);
d9ef75221   Wengang Wang   ocfs2:dlm: avoid ...
718
  			spin_unlock(&dlm->ast_lock);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
719
720
721
722
723
724
725
726
727
728
  
  			dlm_lockres_calc_usage(dlm, res);
  
  in_progress:
  
  			spin_lock(&dlm->spinlock);
  			/* if the lock was in-progress, stick
  			 * it on the back of the list */
  			if (delay) {
  				spin_lock(&res->spinlock);
ddc09c8dd   Kurt Hackel   ocfs2_dlm: Fixes ...
729
  				__dlm_dirty_lockres(dlm, res);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
730
731
732
733
734
735
736
  				spin_unlock(&res->spinlock);
  			}
  			dlm_lockres_put(res);
  
  			/* unlikely, but we may need to give time to
  			 * other tasks */
  			if (!--n) {
8e17d16f4   Sunil Mushran   ocfs2/dlm: Cleanu...
737
738
739
  				mlog(0, "%s: Throttling dlm thread
  ",
  				     dlm->name);
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
740
741
742
743
744
745
746
747
748
  				break;
  			}
  		}
  
  		spin_unlock(&dlm->spinlock);
  		dlm_flush_asts(dlm);
  
  		/* yield and continue right away if there is more work to do */
  		if (!n) {
f85cd47a5   Kurt Hackel   ocfs2: use cond_r...
749
  			cond_resched();
6714d8e86   Kurt Hackel   [PATCH] OCFS2: Th...
750
751
752
753
754
755
756
757
758
759
760
761
762
  			continue;
  		}
  
  		wait_event_interruptible_timeout(dlm->dlm_thread_wq,
  						 !dlm_dirty_list_empty(dlm) ||
  						 kthread_should_stop(),
  						 timeout);
  	}
  
  	mlog(0, "quitting DLM thread
  ");
  	return 0;
  }