Re: [PATCH 1/3] tracing/kprobe: Add PERF_EVENT_IOC_QUERY_KPROBE ioctl

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 8/6/19 4:41 PM, Daniel Xu wrote:
> It's useful to know kprobe's nmissed and nhit stats. For example with
> tracing tools, it's important to know when events may have been lost.
> There is currently no way to get that information from the perf API.
> This patch adds a new ioctl that lets users query this information.
> ---
>   include/linux/trace_events.h    |  6 ++++++
>   include/uapi/linux/perf_event.h | 23 +++++++++++++++++++++++
>   kernel/events/core.c            | 11 +++++++++++
>   kernel/trace/trace_kprobe.c     | 25 +++++++++++++++++++++++++
>   4 files changed, 65 insertions(+)
> 
> diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
> index 5150436783e8..28faf115e0b8 100644
> --- a/include/linux/trace_events.h
> +++ b/include/linux/trace_events.h
> @@ -586,6 +586,12 @@ extern int bpf_get_kprobe_info(const struct perf_event *event,
>   			       u32 *fd_type, const char **symbol,
>   			       u64 *probe_offset, u64 *probe_addr,
>   			       bool perf_type_tracepoint);
> +extern int perf_event_query_kprobe(struct perf_event *event, void __user *info);
> +#else
> +int perf_event_query_kprobe(struct perf_event *event, void __user *info)
> +{
> +	return -EOPNOTSUPP;
> +}
>   #endif
>   #ifdef CONFIG_UPROBE_EVENTS
>   extern int  perf_uprobe_init(struct perf_event *event,
> diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
> index 7198ddd0c6b1..4a5e18606baf 100644
> --- a/include/uapi/linux/perf_event.h
> +++ b/include/uapi/linux/perf_event.h
> @@ -447,6 +447,28 @@ struct perf_event_query_bpf {
>   	__u32	ids[0];
>   };
>   
> +/*
> + * Structure used by below PERF_EVENT_IOC_QUERY_KPROE command
> + * to query information about the kprobe attached to the perf
> + * event.
> + */
> +struct perf_event_query_kprobe {
> +       /*
> +        * Size of structure for forward/backward compatibility
> +        */
> +       __u32   size;
> +       /*
> +        * Set by the kernel to indicate number of times this kprobe
> +        * was temporarily disabled
> +        */
> +       __u64   nmissed;
> +       /*
> +        * Set by the kernel to indicate number of times this kprobe
> +        * was hit
> +        */
> +       __u64   nhit;
> +};
> +
>   /*
>    * Ioctls that can be done on a perf event fd:
>    */
> @@ -462,6 +484,7 @@ struct perf_event_query_bpf {
>   #define PERF_EVENT_IOC_PAUSE_OUTPUT		_IOW('$', 9, __u32)
>   #define PERF_EVENT_IOC_QUERY_BPF		_IOWR('$', 10, struct perf_event_query_bpf *)
>   #define PERF_EVENT_IOC_MODIFY_ATTRIBUTES	_IOW('$', 11, struct perf_event_attr *)
> +#define PERF_EVENT_IOC_QUERY_KPROBE		_IOWR('$', 12, struct perf_event_query_kprobe *)
>   
>   enum perf_event_ioc_flags {
>   	PERF_IOC_FLAG_GROUP		= 1U << 0,
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 026a14541a38..d61c3ac5da4f 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -5061,6 +5061,10 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd);
>   static int perf_copy_attr(struct perf_event_attr __user *uattr,
>   			  struct perf_event_attr *attr);
>   
> +#ifdef CONFIG_KPROBE_EVENTS
> +static struct pmu perf_kprobe;
> +#endif /* CONFIG_KPROBE_EVENTS */
> +
>   static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
>   {
>   	void (*func)(struct perf_event *);
> @@ -5143,6 +5147,13 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
>   
>   		return perf_event_modify_attr(event,  &new_attr);
>   	}
> +#ifdef CONFIG_KPROBE_EVENTS
> +        case PERF_EVENT_IOC_QUERY_KPROBE:
> +		if (event->attr.type != perf_kprobe.type)
> +			return -EINVAL;
> +
> +                return perf_event_query_kprobe(event, (void __user *)arg);
> +#endif /* CONFIG_KPROBE_EVENTS */
>   	default:
>   		return -ENOTTY;
>   	}
> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
> index 9d483ad9bb6c..5449182f3056 100644
> --- a/kernel/trace/trace_kprobe.c
> +++ b/kernel/trace/trace_kprobe.c
> @@ -196,6 +196,31 @@ bool trace_kprobe_error_injectable(struct trace_event_call *call)
>   	return within_error_injection_list(trace_kprobe_address(tk));
>   }
>   
> +int perf_event_query_kprobe(struct perf_event *event, void __user *info)
> +{
> +	struct perf_event_query_kprobe __user *uquery = info;
> +	struct perf_event_query_kprobe query = {};
> +	struct trace_event_call *call = event->tp_event;
> +	struct trace_kprobe *tk = (struct trace_kprobe *)call->data;
> +	u64 nmissed, nhit;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +	if (copy_from_user(&query, uquery, sizeof(query)))
> +		return -EFAULT;
> +	if (query.size != sizeof(query))
> +		return -EINVAL;

Note that here we did not handle any backward or forward compatibility.

> +
> +	nhit = trace_kprobe_nhit(tk);
> +	nmissed = tk->rp.kp.nmissed;
> +
> +	if (copy_to_user(&uquery->nmissed, &nmissed, sizeof(nmissed)) ||
> +	    copy_to_user(&uquery->nhit, &nhit, sizeof(nhit)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>   static int register_kprobe_event(struct trace_kprobe *tk);
>   static int unregister_kprobe_event(struct trace_kprobe *tk);
>   
> 




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux