From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751710AbdIENws (ORCPT ); Tue, 5 Sep 2017 09:52:48 -0400 Received: from mga11.intel.com ([192.55.52.93]:53894 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751159AbdIENwn (ORCPT ); Tue, 5 Sep 2017 09:52:43 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,480,1498546800"; d="scan'208";a="897247732" From: Alexander Shishkin To: Peter Zijlstra Cc: Ingo Molnar , linux-kernel@vger.kernel.org, acme@redhat.com, kirill.shutemov@linux.intel.com, Borislav Petkov , rric@kernel.org, Alexander Shishkin Subject: [RFC PATCH 14/17] perf: Add ioctl(REATTACH) for detached events Date: Tue, 5 Sep 2017 16:30:23 +0300 Message-Id: <20170905133026.13689-15-alexander.shishkin@linux.intel.com> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20170905133026.13689-1-alexander.shishkin@linux.intel.com> References: <20170905133026.13689-1-alexander.shishkin@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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