Merge branch 'sched-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / fs / gfs2 / locking / dlm / thread.c
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 "lock_dlm.h"
11
12 static inline int no_work(struct gdlm_ls *ls)
13 {
14         int ret;
15
16         spin_lock(&ls->async_lock);
17         ret = list_empty(&ls->submit);
18         spin_unlock(&ls->async_lock);
19
20         return ret;
21 }
22
23 static int gdlm_thread(void *data)
24 {
25         struct gdlm_ls *ls = (struct gdlm_ls *) data;
26         struct gdlm_lock *lp = NULL;
27
28         while (!kthread_should_stop()) {
29                 wait_event_interruptible(ls->thread_wait,
30                                 !no_work(ls) || kthread_should_stop());
31
32                 spin_lock(&ls->async_lock);
33
34                 if (!list_empty(&ls->submit)) {
35                         lp = list_entry(ls->submit.next, struct gdlm_lock,
36                                         delay_list);
37                         list_del_init(&lp->delay_list);
38                         spin_unlock(&ls->async_lock);
39                         gdlm_do_lock(lp);
40                         spin_lock(&ls->async_lock);
41                 }
42                 spin_unlock(&ls->async_lock);
43         }
44
45         return 0;
46 }
47
48 int gdlm_init_threads(struct gdlm_ls *ls)
49 {
50         struct task_struct *p;
51         int error;
52
53         p = kthread_run(gdlm_thread, ls, "lock_dlm");
54         error = IS_ERR(p);
55         if (error) {
56                 log_error("can't start lock_dlm thread %d", error);
57                 return error;
58         }
59         ls->thread = p;
60
61         return 0;
62 }
63
64 void gdlm_release_threads(struct gdlm_ls *ls)
65 {
66         kthread_stop(ls->thread);
67 }
68