size_t                  entry_data_size;
        int                     nr_maxactive;
 
-       void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip,
-                             struct pt_regs *regs, void *entry_data);
+       int (*entry_handler)(struct fprobe *fp, unsigned long entry_ip,
+                            struct pt_regs *regs, void *entry_data);
        void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip,
                             struct pt_regs *regs, void *entry_data);
 };
 
        return err;
 }
 
-static void
+static int
 kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip,
                          struct pt_regs *regs, void *data)
 {
        struct bpf_kprobe_multi_link *link;
 
+       link = container_of(fp, struct bpf_kprobe_multi_link, fp);
+       kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs);
+       return 0;
+}
+
+static void
+kprobe_multi_link_exit_handler(struct fprobe *fp, unsigned long fentry_ip,
+                              struct pt_regs *regs, void *data)
+{
+       struct bpf_kprobe_multi_link *link;
+
        link = container_of(fp, struct bpf_kprobe_multi_link, fp);
        kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs);
 }
                goto error;
 
        if (flags & BPF_F_KPROBE_MULTI_RETURN)
-               link->fp.exit_handler = kprobe_multi_link_handler;
+               link->fp.exit_handler = kprobe_multi_link_exit_handler;
        else
                link->fp.entry_handler = kprobe_multi_link_handler;
 
 
        struct rethook_node *rh = NULL;
        struct fprobe *fp;
        void *entry_data = NULL;
-       int bit;
+       int bit, ret;
 
        fp = container_of(ops, struct fprobe, ops);
        if (fprobe_disabled(fp))
        }
 
        if (fp->entry_handler)
-               fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data);
-
-       if (rh)
-               rethook_hook(rh, ftrace_get_regs(fregs), true);
+               ret = fp->entry_handler(fp, ip, ftrace_get_regs(fregs), entry_data);
 
+       /* If entry_handler returns !0, nmissed is not counted. */
+       if (rh) {
+               if (ret)
+                       rethook_recycle(rh);
+               else
+                       rethook_hook(rh, ftrace_get_regs(fregs), true);
+       }
 out:
        ftrace_test_recursion_unlock(bit);
 }
 
        return nest(value + 2);
 }
 
-static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip,
+static notrace int fp_entry_handler(struct fprobe *fp, unsigned long ip,
                                     struct pt_regs *regs, void *data)
 {
        KUNIT_EXPECT_FALSE(current_test, preemptible());
                        *(u32 *)data = entry_val;
        } else
                KUNIT_EXPECT_NULL(current_test, data);
+
+       return 0;
 }
 
 static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip,
                KUNIT_EXPECT_NULL(current_test, data);
 }
 
-static notrace void nest_entry_handler(struct fprobe *fp, unsigned long ip,
+static notrace int nest_entry_handler(struct fprobe *fp, unsigned long ip,
                                     struct pt_regs *regs, void *data)
 {
        KUNIT_EXPECT_FALSE(current_test, preemptible());
+       return 0;
 }
 
 static notrace void nest_exit_handler(struct fprobe *fp, unsigned long ip,
 
        stack_trace_print(stacks, len, 24);
 }
 
-static void sample_entry_handler(struct fprobe *fp, unsigned long ip,
-                                struct pt_regs *regs, void *data)
+static int sample_entry_handler(struct fprobe *fp, unsigned long ip,
+                               struct pt_regs *regs, void *data)
 {
        if (use_trace)
                /*
        nhit++;
        if (stackdump)
                show_backtrace();
+       return 0;
 }
 
 static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs,