From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751921AbdIENfO (ORCPT ); Tue, 5 Sep 2017 09:35:14 -0400 Received: from mga07.intel.com ([134.134.136.100]:40773 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751864AbdIENfI (ORCPT ); Tue, 5 Sep 2017 09:35:08 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,480,1498546800"; d="scan'208";a="131885887" 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 , Steven Rostedt Subject: [RFC PATCH 04/17] tracefs: Add ->unlink callback to tracefs_dir_ops Date: Tue, 5 Sep 2017 16:30:13 +0300 Message-Id: <20170905133026.13689-5-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 In addition to mkdir and rmdir, also allow unlink operation within the 'instances' directory if such callback is defined. Signed-off-by: Alexander Shishkin Cc: Steven Rostedt --- fs/tracefs/inode.c | 36 +++++++++++++++++++++++++++++++++++- include/linux/tracefs.h | 3 ++- kernel/trace/trace.c | 8 +++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index b14f03a655..fba5a0ce07 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -53,6 +53,7 @@ static const struct file_operations tracefs_file_operations = { struct tracefs_dir_ops { int (*mkdir)(const char *name); int (*rmdir)(const char *name); + int (*unlink)(const char *name); }; static char *get_dname(struct dentry *dentry) @@ -124,10 +125,41 @@ static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry) return ret; } +static int tracefs_syscall_unlink(struct inode *inode, struct dentry *dentry) +{ + struct tracefs_dir_ops *tracefs_ops = dentry->d_fsdata; + char *name; + int ret; + + name = get_dname(dentry); + if (!name) + return -ENOMEM; + + /* + * The unlink call can call the generic functions that create + * the files within the tracefs system. It is up to the individual + * unlink routine to handle races. + * This time we need to unlock not only the parent (inode) but + * also the file that is being deleted. + */ + inode_unlock(inode); + inode_unlock(dentry->d_inode); + + ret = tracefs_ops->unlink(name); + + inode_lock_nested(inode, I_MUTEX_PARENT); + inode_lock(dentry->d_inode); + + kfree(name); + + return ret; +} + static const struct inode_operations tracefs_dir_inode_operations = { .lookup = simple_lookup, .mkdir = tracefs_syscall_mkdir, .rmdir = tracefs_syscall_rmdir, + .unlink = tracefs_syscall_unlink, }; static struct inode *tracefs_get_inode(struct super_block *sb) @@ -485,7 +517,8 @@ struct dentry *tracefs_create_dir(const char *name, struct dentry *parent) */ struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent, int (*mkdir)(const char *name), - int (*rmdir)(const char *name)) + int (*rmdir)(const char *name), + int (*unlink)(const char *name)) { struct tracefs_dir_ops *tracefs_ops = parent ? parent->d_fsdata : NULL; struct dentry *dentry; @@ -505,6 +538,7 @@ struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *pare tracefs_ops->mkdir = mkdir; tracefs_ops->rmdir = rmdir; + tracefs_ops->unlink = unlink; dentry->d_fsdata = tracefs_ops; return dentry; diff --git a/include/linux/tracefs.h b/include/linux/tracefs.h index 5b727a17be..e5bd1f01b6 100644 --- a/include/linux/tracefs.h +++ b/include/linux/tracefs.h @@ -36,7 +36,8 @@ void tracefs_remove_recursive(struct dentry *dentry); struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent, int (*mkdir)(const char *name), - int (*rmdir)(const char *name)); + int (*rmdir)(const char *name), + int (*unlink)(const char *name)); bool tracefs_initialized(void); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 44004d8aa3..b9abd2029e 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -7792,11 +7792,17 @@ static int instance_rmdir(const char *name) return ret; } +static int instance_unlink(const char *name) +{ + return -EACCES; +} + static __init void create_trace_instances(struct dentry *d_tracer) { trace_instance_dir = tracefs_create_instance_dir("instances", d_tracer, instance_mkdir, - instance_rmdir); + instance_rmdir, + instance_unlink); if (WARN_ON(!trace_instance_dir)) return; } -- 2.14.1