@@ -144,30 +144,26 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
144
144
145
145
/* Since the slot array is not protected by rcu, we need a mutex */
146
146
guard (mutex )(& c -> mutex );
147
- retry :
148
- rcu_read_lock ();
149
- list_for_each_entry_rcu (kip , & c -> pages , list ) {
150
- if (kip -> nused < slots_per_page (c )) {
151
- int i ;
152
-
153
- for (i = 0 ; i < slots_per_page (c ); i ++ ) {
154
- if (kip -> slot_used [i ] == SLOT_CLEAN ) {
155
- kip -> slot_used [i ] = SLOT_USED ;
156
- kip -> nused ++ ;
157
- rcu_read_unlock ( );
158
- return kip -> insns + ( i * c -> insn_size );
147
+ do {
148
+ guard ( rcu ) ();
149
+ list_for_each_entry_rcu (kip , & c -> pages , list ) {
150
+ if (kip -> nused < slots_per_page (c )) {
151
+ int i ;
152
+
153
+ for (i = 0 ; i < slots_per_page (c ); i ++ ) {
154
+ if (kip -> slot_used [i ] == SLOT_CLEAN ) {
155
+ kip -> slot_used [i ] = SLOT_USED ;
156
+ kip -> nused ++ ;
157
+ return kip -> insns + ( i * c -> insn_size );
158
+ }
159
159
}
160
+ /* kip->nused is broken. Fix it. */
161
+ kip -> nused = slots_per_page (c );
162
+ WARN_ON (1 );
160
163
}
161
- /* kip->nused is broken. Fix it. */
162
- kip -> nused = slots_per_page (c );
163
- WARN_ON (1 );
164
164
}
165
- }
166
- rcu_read_unlock ();
167
-
168
165
/* If there are any garbage slots, collect it and try again. */
169
- if (c -> nr_garbage && collect_garbage_slots (c ) == 0 )
170
- goto retry ;
166
+ } while (c -> nr_garbage && collect_garbage_slots (c ) == 0 );
171
167
172
168
/* All out of space. Need to allocate a new page. */
173
169
kip = kmalloc (struct_size (kip , slot_used , slots_per_page (c )), GFP_KERNEL );
@@ -246,25 +242,35 @@ static int collect_garbage_slots(struct kprobe_insn_cache *c)
246
242
return 0 ;
247
243
}
248
244
249
- void __free_insn_slot (struct kprobe_insn_cache * c ,
250
- kprobe_opcode_t * slot , int dirty )
245
+ static long __find_insn_page (struct kprobe_insn_cache * c ,
246
+ kprobe_opcode_t * slot , struct kprobe_insn_page * * pkip )
251
247
{
252
- struct kprobe_insn_page * kip ;
248
+ struct kprobe_insn_page * kip = NULL ;
253
249
long idx ;
254
250
255
- guard (mutex )(& c -> mutex );
256
- rcu_read_lock ();
251
+ guard (rcu )();
257
252
list_for_each_entry_rcu (kip , & c -> pages , list ) {
258
253
idx = ((long )slot - (long )kip -> insns ) /
259
254
(c -> insn_size * sizeof (kprobe_opcode_t ));
260
- if (idx >= 0 && idx < slots_per_page (c ))
261
- goto out ;
255
+ if (idx >= 0 && idx < slots_per_page (c )) {
256
+ * pkip = kip ;
257
+ return idx ;
258
+ }
262
259
}
263
260
/* Could not find this slot. */
264
261
WARN_ON (1 );
265
- kip = NULL ;
266
- out :
267
- rcu_read_unlock ();
262
+ * pkip = NULL ;
263
+ return -1 ;
264
+ }
265
+
266
+ void __free_insn_slot (struct kprobe_insn_cache * c ,
267
+ kprobe_opcode_t * slot , int dirty )
268
+ {
269
+ struct kprobe_insn_page * kip = NULL ;
270
+ long idx ;
271
+
272
+ guard (mutex )(& c -> mutex );
273
+ idx = __find_insn_page (c , slot , & kip );
268
274
/* Mark and sweep: this may sleep */
269
275
if (kip ) {
270
276
/* Check double free */
0 commit comments