* @nmissed: The counter for missing events.
  * @flags: The status flag.
  * @rethook: The rethook data structure. (internal data)
+ * @entry_data_size: The private data storage size.
  * @entry_handler: The callback function for function entry.
  * @exit_handler: The callback function for function exit.
  */
        unsigned long           nmissed;
        unsigned int            flags;
        struct rethook          *rethook;
+       size_t                  entry_data_size;
 
-       void (*entry_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs);
-       void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs);
+       void (*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);
 };
 
 /* This fprobe is soft-disabled. */
 
 
 static void
 kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip,
-                         struct pt_regs *regs)
+                         struct pt_regs *regs, void *data)
 {
        struct bpf_kprobe_multi_link *link;
 
 
 struct fprobe_rethook_node {
        struct rethook_node node;
        unsigned long entry_ip;
+       char data[];
 };
 
 static void fprobe_handler(unsigned long ip, unsigned long parent_ip,
                           struct ftrace_ops *ops, struct ftrace_regs *fregs)
 {
        struct fprobe_rethook_node *fpr;
-       struct rethook_node *rh;
+       struct rethook_node *rh = NULL;
        struct fprobe *fp;
+       void *entry_data = NULL;
        int bit;
 
        fp = container_of(ops, struct fprobe, ops);
                return;
        }
 
-       if (fp->entry_handler)
-               fp->entry_handler(fp, ip, ftrace_get_regs(fregs));
-
        if (fp->exit_handler) {
                rh = rethook_try_get(fp->rethook);
                if (!rh) {
                }
                fpr = container_of(rh, struct fprobe_rethook_node, node);
                fpr->entry_ip = ip;
-               rethook_hook(rh, ftrace_get_regs(fregs), true);
+               if (fp->entry_data_size)
+                       entry_data = fpr->data;
        }
 
+       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);
+
 out:
        ftrace_test_recursion_unlock(bit);
 }
 
        fpr = container_of(rh, struct fprobe_rethook_node, node);
 
-       fp->exit_handler(fp, fpr->entry_ip, regs);
+       fp->exit_handler(fp, fpr->entry_ip, regs,
+                        fp->entry_data_size ? (void *)fpr->data : NULL);
 }
 NOKPROBE_SYMBOL(fprobe_exit_handler);
 
        for (i = 0; i < size; i++) {
                struct fprobe_rethook_node *node;
 
-               node = kzalloc(sizeof(*node), GFP_KERNEL);
+               node = kzalloc(sizeof(*node) + fp->entry_data_size, GFP_KERNEL);
                if (!node) {
                        rethook_free(fp->rethook);
                        fp->rethook = NULL;
 
        return (value / div_factor) + 1;
 }
 
-static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs)
+static notrace void fp_entry_handler(struct fprobe *fp, unsigned long ip,
+                                    struct pt_regs *regs, void *data)
 {
        KUNIT_EXPECT_FALSE(current_test, preemptible());
        /* This can be called on the fprobe_selftest_target and the fprobe_selftest_target2 */
        entry_val = (rand1 / div_factor);
 }
 
-static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs)
+static notrace void fp_exit_handler(struct fprobe *fp, unsigned long ip,
+                                   struct pt_regs *regs, void *data)
 {
        unsigned long ret = regs_return_value(regs);
 
 
        stack_trace_print(stacks, len, 24);
 }
 
-static void sample_entry_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs)
+static void sample_entry_handler(struct fprobe *fp, unsigned long ip,
+                                struct pt_regs *regs, void *data)
 {
        if (use_trace)
                /*
                show_backtrace();
 }
 
-static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs)
+static void sample_exit_handler(struct fprobe *fp, unsigned long ip, struct pt_regs *regs,
+                               void *data)
 {
        unsigned long rip = instruction_pointer(regs);