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)
{
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);
}
static int symbols_cmp_r(const void *a, const void *b, const void *priv)
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,