@@ -144,30 +144,26 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
144144
145145 /* Since the slot array is not protected by rcu, we need a mutex */
146146 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+ }
159159 }
160+ /* kip->nused is broken. Fix it. */
161+ kip -> nused = slots_per_page (c );
162+ WARN_ON (1 );
160163 }
161- /* kip->nused is broken. Fix it. */
162- kip -> nused = slots_per_page (c );
163- WARN_ON (1 );
164164 }
165- }
166- rcu_read_unlock ();
167-
168165 /* 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 );
171167
172168 /* All out of space. Need to allocate a new page. */
173169 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)
246242 return 0 ;
247243}
248244
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 )
251247{
252- struct kprobe_insn_page * kip ;
248+ struct kprobe_insn_page * kip = NULL ;
253249 long idx ;
254250
255- guard (mutex )(& c -> mutex );
256- rcu_read_lock ();
251+ guard (rcu )();
257252 list_for_each_entry_rcu (kip , & c -> pages , list ) {
258253 idx = ((long )slot - (long )kip -> insns ) /
259254 (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+ }
262259 }
263260 /* Could not find this slot. */
264261 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 );
268274 /* Mark and sweep: this may sleep */
269275 if (kip ) {
270276 /* Check double free */
0 commit comments