Free the kprobe_insn_page data structure asynchronously using call_rcu(). Signed-off-by: Masami Hiramatsu <mhiramat@xxxxxxxxxx> --- kernel/kprobes.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index a9114923da4c..60ffc9d54d87 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -87,6 +87,7 @@ static LIST_HEAD(kprobe_blacklist); */ struct kprobe_insn_page { struct list_head list; + struct rcu_head rcu; kprobe_opcode_t *insns; /* Page of instruction slots */ struct kprobe_insn_cache *cache; int nused; @@ -192,6 +193,13 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c) return slot; } +static void free_kprobe_insn_page(struct rcu_head *head) +{ + struct kprobe_insn_page *kip = container_of(head, typeof(*kip), rcu); + + kfree(kip); +} + /* Return 1 if all garbages are collected, otherwise 0. */ static int collect_one_slot(struct kprobe_insn_page *kip, int idx) { @@ -206,9 +214,8 @@ static int collect_one_slot(struct kprobe_insn_page *kip, int idx) */ if (!list_is_singular(&kip->list)) { list_del_rcu(&kip->list); - synchronize_rcu(); kip->cache->free(kip->insns); - kfree(kip); + call_rcu(&kip->rcu, free_kprobe_insn_page); } return 1; }