18
18
#include "user.h"
19
19
#include "ast.h"
20
20
21
- static void dlm_callback_work (struct work_struct * work )
21
+ static void dlm_run_callback (uint32_t ls_id , uint32_t lkb_id , int8_t mode ,
22
+ uint32_t flags , uint8_t sb_flags , int sb_status ,
23
+ struct dlm_lksb * lksb ,
24
+ void (* astfn )(void * astparam ),
25
+ void (* bastfn )(void * astparam , int mode ),
26
+ void * astparam , const char * res_name ,
27
+ size_t res_length )
22
28
{
23
- struct dlm_callback * cb = container_of (work , struct dlm_callback , work );
24
-
25
- if (cb -> flags & DLM_CB_BAST ) {
26
- trace_dlm_bast (cb -> ls_id , cb -> lkb_id , cb -> mode , cb -> res_name ,
27
- cb -> res_length );
28
- cb -> bastfn (cb -> astparam , cb -> mode );
29
- } else if (cb -> flags & DLM_CB_CAST ) {
30
- trace_dlm_ast (cb -> ls_id , cb -> lkb_id , cb -> sb_status ,
31
- cb -> sb_flags , cb -> res_name , cb -> res_length );
32
- cb -> lkb_lksb -> sb_status = cb -> sb_status ;
33
- cb -> lkb_lksb -> sb_flags = cb -> sb_flags ;
34
- cb -> astfn (cb -> astparam );
29
+ if (flags & DLM_CB_BAST ) {
30
+ trace_dlm_bast (ls_id , lkb_id , mode , res_name , res_length );
31
+ bastfn (astparam , mode );
32
+ } else if (flags & DLM_CB_CAST ) {
33
+ trace_dlm_ast (ls_id , lkb_id , sb_status , sb_flags , res_name ,
34
+ res_length );
35
+ lksb -> sb_status = sb_status ;
36
+ lksb -> sb_flags = sb_flags ;
37
+ astfn (astparam );
35
38
}
39
+ }
36
40
41
+ static void dlm_do_callback (struct dlm_callback * cb )
42
+ {
43
+ dlm_run_callback (cb -> ls_id , cb -> lkb_id , cb -> mode , cb -> flags ,
44
+ cb -> sb_flags , cb -> sb_status , cb -> lkb_lksb ,
45
+ cb -> astfn , cb -> bastfn , cb -> astparam ,
46
+ cb -> res_name , cb -> res_length );
37
47
dlm_free_cb (cb );
38
48
}
39
49
40
- int dlm_queue_lkb_callback (struct dlm_lkb * lkb , uint32_t flags , int mode ,
41
- int status , uint32_t sbflags ,
42
- struct dlm_callback * * cb )
50
+ static void dlm_callback_work (struct work_struct * work )
51
+ {
52
+ struct dlm_callback * cb = container_of (work , struct dlm_callback , work );
53
+
54
+ dlm_do_callback (cb );
55
+ }
56
+
57
+ bool dlm_may_skip_callback (struct dlm_lkb * lkb , uint32_t flags , int mode ,
58
+ int status , uint32_t sbflags , int * copy_lvb )
43
59
{
44
60
struct dlm_rsb * rsb = lkb -> lkb_resource ;
45
- int rv = DLM_ENQUEUE_CALLBACK_SUCCESS ;
46
61
struct dlm_ls * ls = rsb -> res_ls ;
47
- int copy_lvb = 0 ;
48
62
int prev_mode ;
49
63
64
+ if (copy_lvb )
65
+ * copy_lvb = 0 ;
66
+
50
67
if (flags & DLM_CB_BAST ) {
51
68
/* if cb is a bast, it should be skipped if the blocking mode is
52
69
* compatible with the last granted mode
@@ -56,7 +73,7 @@ int dlm_queue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
56
73
log_debug (ls , "skip %x bast mode %d for cast mode %d" ,
57
74
lkb -> lkb_id , mode ,
58
75
lkb -> lkb_last_cast_cb_mode );
59
- goto out ;
76
+ return true ;
60
77
}
61
78
}
62
79
@@ -74,7 +91,7 @@ int dlm_queue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
74
91
(prev_mode > mode && prev_mode > DLM_LOCK_PR )) {
75
92
log_debug (ls , "skip %x add bast mode %d for bast mode %d" ,
76
93
lkb -> lkb_id , mode , prev_mode );
77
- goto out ;
94
+ return true ;
78
95
}
79
96
}
80
97
@@ -85,8 +102,10 @@ int dlm_queue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
85
102
prev_mode = lkb -> lkb_last_cast_cb_mode ;
86
103
87
104
if (!status && lkb -> lkb_lksb -> sb_lvbptr &&
88
- dlm_lvb_operations [prev_mode + 1 ][mode + 1 ])
89
- copy_lvb = 1 ;
105
+ dlm_lvb_operations [prev_mode + 1 ][mode + 1 ]) {
106
+ if (copy_lvb )
107
+ * copy_lvb = 1 ;
108
+ }
90
109
}
91
110
92
111
lkb -> lkb_last_cast_cb_mode = mode ;
@@ -96,11 +115,19 @@ int dlm_queue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
96
115
lkb -> lkb_last_cb_mode = mode ;
97
116
lkb -> lkb_last_cb_flags = flags ;
98
117
118
+ return false;
119
+ }
120
+
121
+ int dlm_get_cb (struct dlm_lkb * lkb , uint32_t flags , int mode ,
122
+ int status , uint32_t sbflags ,
123
+ struct dlm_callback * * cb )
124
+ {
125
+ struct dlm_rsb * rsb = lkb -> lkb_resource ;
126
+ struct dlm_ls * ls = rsb -> res_ls ;
127
+
99
128
* cb = dlm_allocate_cb ();
100
- if (!* cb ) {
101
- rv = DLM_ENQUEUE_CALLBACK_FAILURE ;
102
- goto out ;
103
- }
129
+ if (WARN_ON_ONCE (!* cb ))
130
+ return - ENOMEM ;
104
131
105
132
/* for tracing */
106
133
(* cb )-> lkb_id = lkb -> lkb_id ;
@@ -112,19 +139,34 @@ int dlm_queue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
112
139
(* cb )-> mode = mode ;
113
140
(* cb )-> sb_status = status ;
114
141
(* cb )-> sb_flags = (sbflags & 0x000000FF );
115
- (* cb )-> copy_lvb = copy_lvb ;
116
142
(* cb )-> lkb_lksb = lkb -> lkb_lksb ;
117
143
118
- rv = DLM_ENQUEUE_CALLBACK_NEED_SCHED ;
144
+ return 0 ;
145
+ }
146
+
147
+ static int dlm_get_queue_cb (struct dlm_lkb * lkb , uint32_t flags , int mode ,
148
+ int status , uint32_t sbflags ,
149
+ struct dlm_callback * * cb )
150
+ {
151
+ int rv ;
152
+
153
+ rv = dlm_get_cb (lkb , flags , mode , status , sbflags , cb );
154
+ if (rv )
155
+ return rv ;
119
156
120
- out :
121
- return rv ;
157
+ (* cb )-> astfn = lkb -> lkb_astfn ;
158
+ (* cb )-> bastfn = lkb -> lkb_bastfn ;
159
+ (* cb )-> astparam = lkb -> lkb_astparam ;
160
+ INIT_WORK (& (* cb )-> work , dlm_callback_work );
161
+
162
+ return 0 ;
122
163
}
123
164
124
165
void dlm_add_cb (struct dlm_lkb * lkb , uint32_t flags , int mode , int status ,
125
- uint32_t sbflags )
166
+ uint32_t sbflags )
126
167
{
127
- struct dlm_ls * ls = lkb -> lkb_resource -> res_ls ;
168
+ struct dlm_rsb * rsb = lkb -> lkb_resource ;
169
+ struct dlm_ls * ls = rsb -> res_ls ;
128
170
struct dlm_callback * cb ;
129
171
int rv ;
130
172
@@ -133,34 +175,36 @@ void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
133
175
return ;
134
176
}
135
177
136
- rv = dlm_queue_lkb_callback (lkb , flags , mode , status , sbflags ,
137
- & cb );
138
- switch (rv ) {
139
- case DLM_ENQUEUE_CALLBACK_NEED_SCHED :
140
- cb -> astfn = lkb -> lkb_astfn ;
141
- cb -> bastfn = lkb -> lkb_bastfn ;
142
- cb -> astparam = lkb -> lkb_astparam ;
143
- INIT_WORK (& cb -> work , dlm_callback_work );
144
-
145
- spin_lock_bh (& ls -> ls_cb_lock );
146
- if (test_bit (LSFL_CB_DELAY , & ls -> ls_flags ))
178
+ if (dlm_may_skip_callback (lkb , flags , mode , status , sbflags , NULL ))
179
+ return ;
180
+
181
+ spin_lock_bh (& ls -> ls_cb_lock );
182
+ if (test_bit (LSFL_CB_DELAY , & ls -> ls_flags )) {
183
+ rv = dlm_get_queue_cb (lkb , flags , mode , status , sbflags , & cb );
184
+ if (!rv )
147
185
list_add (& cb -> list , & ls -> ls_cb_delay );
148
- else
149
- queue_work (ls -> ls_callback_wq , & cb -> work );
150
- spin_unlock_bh (& ls -> ls_cb_lock );
151
- break ;
152
- case DLM_ENQUEUE_CALLBACK_SUCCESS :
153
- break ;
154
- case DLM_ENQUEUE_CALLBACK_FAILURE :
155
- fallthrough ;
156
- default :
157
- WARN_ON_ONCE (1 );
158
- break ;
186
+ } else {
187
+ if (test_bit (LSFL_SOFTIRQ , & ls -> ls_flags )) {
188
+ dlm_run_callback (ls -> ls_global_id , lkb -> lkb_id , mode , flags ,
189
+ sbflags , status , lkb -> lkb_lksb ,
190
+ lkb -> lkb_astfn , lkb -> lkb_bastfn ,
191
+ lkb -> lkb_astparam , rsb -> res_name ,
192
+ rsb -> res_length );
193
+ } else {
194
+ rv = dlm_get_queue_cb (lkb , flags , mode , status , sbflags , & cb );
195
+ if (!rv )
196
+ queue_work (ls -> ls_callback_wq , & cb -> work );
197
+ }
159
198
}
199
+ spin_unlock_bh (& ls -> ls_cb_lock );
160
200
}
161
201
162
202
int dlm_callback_start (struct dlm_ls * ls )
163
203
{
204
+ if (!test_bit (LSFL_FS , & ls -> ls_flags ) ||
205
+ test_bit (LSFL_SOFTIRQ , & ls -> ls_flags ))
206
+ return 0 ;
207
+
164
208
ls -> ls_callback_wq = alloc_ordered_workqueue ("dlm_callback" ,
165
209
WQ_HIGHPRI | WQ_MEM_RECLAIM );
166
210
if (!ls -> ls_callback_wq ) {
@@ -178,13 +222,15 @@ void dlm_callback_stop(struct dlm_ls *ls)
178
222
179
223
void dlm_callback_suspend (struct dlm_ls * ls )
180
224
{
181
- if (ls -> ls_callback_wq ) {
182
- spin_lock_bh (& ls -> ls_cb_lock );
183
- set_bit (LSFL_CB_DELAY , & ls -> ls_flags );
184
- spin_unlock_bh (& ls -> ls_cb_lock );
225
+ if (!test_bit (LSFL_FS , & ls -> ls_flags ))
226
+ return ;
227
+
228
+ spin_lock_bh (& ls -> ls_cb_lock );
229
+ set_bit (LSFL_CB_DELAY , & ls -> ls_flags );
230
+ spin_unlock_bh (& ls -> ls_cb_lock );
185
231
232
+ if (ls -> ls_callback_wq )
186
233
flush_workqueue (ls -> ls_callback_wq );
187
- }
188
234
}
189
235
190
236
#define MAX_CB_QUEUE 25
@@ -195,14 +241,18 @@ void dlm_callback_resume(struct dlm_ls *ls)
195
241
int count = 0 , sum = 0 ;
196
242
bool empty ;
197
243
198
- if (!ls -> ls_callback_wq )
244
+ if (!test_bit ( LSFL_FS , & ls -> ls_flags ) )
199
245
return ;
200
246
201
247
more :
202
248
spin_lock_bh (& ls -> ls_cb_lock );
203
249
list_for_each_entry_safe (cb , safe , & ls -> ls_cb_delay , list ) {
204
250
list_del (& cb -> list );
205
- queue_work (ls -> ls_callback_wq , & cb -> work );
251
+ if (test_bit (LSFL_SOFTIRQ , & ls -> ls_flags ))
252
+ dlm_do_callback (cb );
253
+ else
254
+ queue_work (ls -> ls_callback_wq , & cb -> work );
255
+
206
256
count ++ ;
207
257
if (count == MAX_CB_QUEUE )
208
258
break ;
0 commit comments