Messages in this thread Patch in this message | | | From | Alexander Shishkin <> | Subject | [RFC PATCH 14/17] perf: Add ioctl(REATTACH) for detached events | Date | Tue, 5 Sep 2017 16:30:23 +0300 |
| |
This adds an ioctl command to demote a detached event to a 'normal' one that gets destroyed when its file descriptor is closed. It can still be used to mmap the buffers, but not very useful otherwise.
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> --- include/uapi/linux/perf_event.h | 1 + kernel/events/core.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 4cdd4fab9d..ae54bd496d 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -435,6 +435,7 @@ struct perf_event_attr { #define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) #define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) #define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) +#define PERF_EVENT_IOC_REATTACH _IO ('$', 10) enum perf_event_ioc_flags { PERF_IOC_FLAG_GROUP = 1U << 0, diff --git a/kernel/events/core.c b/kernel/events/core.c index f0b77b33b4..fbee221d19 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4532,7 +4532,19 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel); */ static int perf_release(struct inode *inode, struct file *file) { - perf_event_release_kernel(file->private_data); + struct perf_event *event = file->private_data; + + /* + * For a DETACHED event, perf_release() can't have the last reference, + * because we grabbed one extra in the sys_perf_event_open, IOW it is + * always put_event(). In order for it to be the last reference, we'd + * first need to ioctl(REATTACH) on this event, which would drop the + * PERF_ATTACH_DETACHED attach state. + */ + if (event->attach_state & PERF_ATTACH_DETACHED) + put_event(event); + else + perf_event_release_kernel(file->private_data); return 0; } @@ -4885,6 +4897,11 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon void (*func)(struct perf_event *); u32 flags = arg; + if (event->attach_state & PERF_ATTACH_DETACHED && + cmd != PERF_EVENT_IOC_REATTACH && + cmd != PERF_EVENT_IOC_ID) + return -EINVAL; + switch (cmd) { case PERF_EVENT_IOC_ENABLE: func = _perf_event_enable; @@ -4948,6 +4965,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon rcu_read_unlock(); return 0; } + case PERF_EVENT_IOC_REATTACH: + /* + * DETACHED state is serialized on ctx::mutex + */ + if (!is_detached_event(event)) + return -EINVAL; + + event->attach_state &= ~PERF_ATTACH_DETACHED; + tracefs_remove(event->dent); + event->dent = NULL; + put_event(event); /* can't be last */ + + return 0; default: return -ENOTTY; } -- 2.14.1
| |