David Teigland | 869d81d | 2006-01-17 08:47:12 +0000 | [diff] [blame] | 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 |
Steven Whitehouse | e9fc2aa | 2006-09-01 11:05:15 -0400 | [diff] [blame] | 7 | * of the GNU General Public License version 2. |
David Teigland | 869d81d | 2006-01-17 08:47:12 +0000 | [diff] [blame] | 8 | */ |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 9 | |
| 10 | #include "lock_dlm.h" |
| 11 | |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 12 | static inline int no_work(struct gdlm_ls *ls) |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 13 | { |
| 14 | int ret; |
| 15 | |
| 16 | spin_lock(&ls->async_lock); |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 17 | ret = list_empty(&ls->submit); |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 18 | spin_unlock(&ls->async_lock); |
| 19 | |
| 20 | return ret; |
| 21 | } |
| 22 | |
| 23 | static 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 Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 36 | static int gdlm_thread(void *data) |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 37 | { |
| 38 | struct gdlm_ls *ls = (struct gdlm_ls *) data; |
| 39 | struct gdlm_lock *lp = NULL; |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 40 | |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 41 | while (!kthread_should_stop()) { |
David Teigland | 8cbc434 | 2007-11-07 09:03:56 -0600 | [diff] [blame] | 42 | wait_event_interruptible(ls->thread_wait, |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 43 | !no_work(ls) || kthread_should_stop()); |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 44 | |
| 45 | spin_lock(&ls->async_lock); |
| 46 | |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 47 | if (!list_empty(&ls->submit)) { |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 48 | lp = list_entry(ls->submit.next, struct gdlm_lock, |
| 49 | delay_list); |
| 50 | list_del_init(&lp->delay_list); |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 51 | spin_unlock(&ls->async_lock); |
David Teigland | 8d3b35a | 2006-02-23 10:00:56 +0000 | [diff] [blame] | 52 | gdlm_do_lock(lp); |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 53 | 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 Whitehouse | 1c089c3 | 2006-09-07 15:50:20 -0400 | [diff] [blame] | 58 | ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL); |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 59 | spin_lock(&ls->async_lock); |
| 60 | } |
| 61 | spin_unlock(&ls->async_lock); |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | return 0; |
| 65 | } |
| 66 | |
| 67 | int gdlm_init_threads(struct gdlm_ls *ls) |
| 68 | { |
| 69 | struct task_struct *p; |
| 70 | int error; |
| 71 | |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 72 | p = kthread_run(gdlm_thread, ls, "lock_dlm"); |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 73 | error = IS_ERR(p); |
| 74 | if (error) { |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 75 | log_error("can't start lock_dlm thread %d", error); |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 76 | return error; |
| 77 | } |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 78 | ls->thread = p; |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 79 | |
| 80 | return 0; |
| 81 | } |
| 82 | |
| 83 | void gdlm_release_threads(struct gdlm_ls *ls) |
| 84 | { |
Steven Whitehouse | f3c9d38 | 2008-05-21 17:21:42 +0100 | [diff] [blame^] | 85 | kthread_stop(ls->thread); |
David Teigland | 29b7998 | 2006-01-16 16:52:38 +0000 | [diff] [blame] | 86 | } |
| 87 | |