blob: f30350abd62fc3a4b6cfcac5b01546279351e1b0 [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
Steven Whitehousef3c9d382008-05-21 17:21:42 +010012static inline int no_work(struct gdlm_ls *ls)
David Teigland29b79982006-01-16 16:52:38 +000013{
14 int ret;
15
16 spin_lock(&ls->async_lock);
Steven Whitehousef3c9d382008-05-21 17:21:42 +010017 ret = list_empty(&ls->submit);
David Teigland29b79982006-01-16 16:52:38 +000018 spin_unlock(&ls->async_lock);
19
20 return ret;
21}
22
23static inline int check_drop(struct gdlm_ls *ls)
24{
25 if (!ls->drop_locks_count)
26 return 0;
27
28 if (time_after(jiffies, ls->drop_time + ls->drop_locks_period * HZ)) {
29 ls->drop_time = jiffies;
30 if (ls->all_locks_count >= ls->drop_locks_count)
31 return 1;
32 }
33 return 0;
34}
35
Steven Whitehousef3c9d382008-05-21 17:21:42 +010036static int gdlm_thread(void *data)
David Teigland29b79982006-01-16 16:52:38 +000037{
38 struct gdlm_ls *ls = (struct gdlm_ls *) data;
39 struct gdlm_lock *lp = NULL;
David Teigland29b79982006-01-16 16:52:38 +000040
David Teigland29b79982006-01-16 16:52:38 +000041 while (!kthread_should_stop()) {
David Teigland8cbc4342007-11-07 09:03:56 -060042 wait_event_interruptible(ls->thread_wait,
Steven Whitehousef3c9d382008-05-21 17:21:42 +010043 !no_work(ls) || kthread_should_stop());
David Teigland29b79982006-01-16 16:52:38 +000044
45 spin_lock(&ls->async_lock);
46
Steven Whitehousef3c9d382008-05-21 17:21:42 +010047 if (!list_empty(&ls->submit)) {
David Teigland29b79982006-01-16 16:52:38 +000048 lp = list_entry(ls->submit.next, struct gdlm_lock,
49 delay_list);
50 list_del_init(&lp->delay_list);
Steven Whitehousef3c9d382008-05-21 17:21:42 +010051 spin_unlock(&ls->async_lock);
David Teigland8d3b35a2006-02-23 10:00:56 +000052 gdlm_do_lock(lp);
Steven Whitehousef3c9d382008-05-21 17:21:42 +010053 spin_lock(&ls->async_lock);
54 }
55 /* Does this ever happen these days? I hope not anyway */
56 if (check_drop(ls)) {
57 spin_unlock(&ls->async_lock);
Steven Whitehouse1c089c32006-09-07 15:50:20 -040058 ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL);
Steven Whitehousef3c9d382008-05-21 17:21:42 +010059 spin_lock(&ls->async_lock);
60 }
61 spin_unlock(&ls->async_lock);
David Teigland29b79982006-01-16 16:52:38 +000062 }
63
64 return 0;
65}
66
67int gdlm_init_threads(struct gdlm_ls *ls)
68{
69 struct task_struct *p;
70 int error;
71
Steven Whitehousef3c9d382008-05-21 17:21:42 +010072 p = kthread_run(gdlm_thread, ls, "lock_dlm");
David Teigland29b79982006-01-16 16:52:38 +000073 error = IS_ERR(p);
74 if (error) {
Steven Whitehousef3c9d382008-05-21 17:21:42 +010075 log_error("can't start lock_dlm thread %d", error);
David Teigland29b79982006-01-16 16:52:38 +000076 return error;
77 }
Steven Whitehousef3c9d382008-05-21 17:21:42 +010078 ls->thread = p;
David Teigland29b79982006-01-16 16:52:38 +000079
80 return 0;
81}
82
83void gdlm_release_threads(struct gdlm_ls *ls)
84{
Steven Whitehousef3c9d382008-05-21 17:21:42 +010085 kthread_stop(ls->thread);
David Teigland29b79982006-01-16 16:52:38 +000086}
87