1 /******************************************************************************
2 *******************************************************************************
4 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
5 ** Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
7 ** This copyrighted material is made available to anyone wishing to use,
8 ** modify, copy, or redistribute it subject to the terms and conditions
9 ** of the GNU General Public License v.2.
11 *******************************************************************************
12 ******************************************************************************/
14 #include "dlm_internal.h"
21 static struct list_head ast_queue
;
22 static spinlock_t ast_queue_lock
;
23 static struct task_struct
* astd_task
;
24 static unsigned long astd_wakeflags
;
25 static struct mutex astd_running
;
28 void dlm_del_ast(struct dlm_lkb
*lkb
)
30 spin_lock(&ast_queue_lock
);
31 if (lkb
->lkb_ast_type
& (AST_COMP
| AST_BAST
))
32 list_del(&lkb
->lkb_astqueue
);
33 spin_unlock(&ast_queue_lock
);
36 void dlm_add_ast(struct dlm_lkb
*lkb
, int type
, int mode
)
38 if (lkb
->lkb_flags
& DLM_IFL_USER
) {
39 dlm_user_add_ast(lkb
, type
, mode
);
43 spin_lock(&ast_queue_lock
);
44 if (!(lkb
->lkb_ast_type
& (AST_COMP
| AST_BAST
))) {
45 kref_get(&lkb
->lkb_ref
);
46 list_add_tail(&lkb
->lkb_astqueue
, &ast_queue
);
47 lkb
->lkb_ast_first
= type
;
50 /* sanity check, this should not happen */
52 if ((type
== AST_COMP
) && (lkb
->lkb_ast_type
& AST_COMP
))
53 log_print("repeat cast %d castmode %d lock %x %s",
54 mode
, lkb
->lkb_castmode
,
55 lkb
->lkb_id
, lkb
->lkb_resource
->res_name
);
57 lkb
->lkb_ast_type
|= type
;
59 lkb
->lkb_bastmode
= mode
;
61 lkb
->lkb_castmode
= mode
;
62 spin_unlock(&ast_queue_lock
);
64 set_bit(WAKE_ASTS
, &astd_wakeflags
);
65 wake_up_process(astd_task
);
68 static void process_asts(void)
70 struct dlm_ls
*ls
= NULL
;
71 struct dlm_rsb
*r
= NULL
;
73 void (*castfn
) (void *astparam
);
74 void (*bastfn
) (void *astparam
, int mode
);
75 int type
, first
, bastmode
, castmode
, do_bast
, do_cast
, last_castmode
;
78 spin_lock(&ast_queue_lock
);
79 list_for_each_entry(lkb
, &ast_queue
, lkb_astqueue
) {
80 r
= lkb
->lkb_resource
;
83 if (dlm_locking_stopped(ls
))
86 list_del(&lkb
->lkb_astqueue
);
87 type
= lkb
->lkb_ast_type
;
88 lkb
->lkb_ast_type
= 0;
89 first
= lkb
->lkb_ast_first
;
90 lkb
->lkb_ast_first
= 0;
91 bastmode
= lkb
->lkb_bastmode
;
92 castmode
= lkb
->lkb_castmode
;
93 castfn
= lkb
->lkb_astfn
;
94 bastfn
= lkb
->lkb_bastfn
;
95 spin_unlock(&ast_queue_lock
);
97 do_cast
= (type
& AST_COMP
) && castfn
;
98 do_bast
= (type
& AST_BAST
) && bastfn
;
100 /* Skip a bast if its blocking mode is compatible with the
101 granted mode of the preceding cast. */
104 if (first
== AST_COMP
)
105 last_castmode
= castmode
;
107 last_castmode
= lkb
->lkb_castmode_done
;
108 if (dlm_modes_compat(bastmode
, last_castmode
))
112 if (first
== AST_COMP
) {
114 castfn(lkb
->lkb_astparam
);
116 bastfn(lkb
->lkb_astparam
, bastmode
);
117 } else if (first
== AST_BAST
) {
119 bastfn(lkb
->lkb_astparam
, bastmode
);
121 castfn(lkb
->lkb_astparam
);
123 log_error(ls
, "bad ast_first %d ast_type %d",
128 lkb
->lkb_castmode_done
= castmode
;
130 lkb
->lkb_bastmode_done
= bastmode
;
132 /* this removes the reference added by dlm_add_ast
133 and may result in the lkb being freed */
139 spin_unlock(&ast_queue_lock
);
142 static inline int no_asts(void)
146 spin_lock(&ast_queue_lock
);
147 ret
= list_empty(&ast_queue
);
148 spin_unlock(&ast_queue_lock
);
152 static int dlm_astd(void *data
)
154 while (!kthread_should_stop()) {
155 set_current_state(TASK_INTERRUPTIBLE
);
156 if (!test_bit(WAKE_ASTS
, &astd_wakeflags
))
158 set_current_state(TASK_RUNNING
);
160 mutex_lock(&astd_running
);
161 if (test_and_clear_bit(WAKE_ASTS
, &astd_wakeflags
))
163 mutex_unlock(&astd_running
);
168 void dlm_astd_wake(void)
171 set_bit(WAKE_ASTS
, &astd_wakeflags
);
172 wake_up_process(astd_task
);
176 int dlm_astd_start(void)
178 struct task_struct
*p
;
181 INIT_LIST_HEAD(&ast_queue
);
182 spin_lock_init(&ast_queue_lock
);
183 mutex_init(&astd_running
);
185 p
= kthread_run(dlm_astd
, NULL
, "dlm_astd");
193 void dlm_astd_stop(void)
195 kthread_stop(astd_task
);
198 void dlm_astd_suspend(void)
200 mutex_lock(&astd_running
);
203 void dlm_astd_resume(void)
205 mutex_unlock(&astd_running
);