From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751861AbdIENfF (ORCPT ); Tue, 5 Sep 2017 09:35:05 -0400 Received: from mga05.intel.com ([192.55.52.43]:41127 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751783AbdIENfD (ORCPT ); Tue, 5 Sep 2017 09:35:03 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,480,1498546800"; d="scan'208";a="897242879" 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 03/17] tracefs: De-globalize instances' callbacks Date: Tue, 5 Sep 2017 16:30:12 +0300 Message-Id: <20170905133026.13689-4-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 Currently, tracefs has exactly one special 'instances' subdirectory, where the caller can have their own .mkdir/.rmdir callbacks, which allow the caller to handle user's mkdir/rmdir inside that directory. Tracefs allows one set of these callbacks (tracefs_dir_ops). This patch de-globalizes tracefs_dir_ops so that it's possible to have multiple such subdirectories. Signed-off-by: Alexander Shishkin Cc: Steven Rostedt --- fs/tracefs/inode.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index bea8ad876b..b14f03a655 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -50,10 +50,10 @@ static const struct file_operations tracefs_file_operations = { .llseek = noop_llseek, }; -static struct tracefs_dir_ops { +struct tracefs_dir_ops { int (*mkdir)(const char *name); int (*rmdir)(const char *name); -} tracefs_ops; +}; static char *get_dname(struct dentry *dentry) { @@ -72,6 +72,7 @@ static char *get_dname(struct dentry *dentry) static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode) { + struct tracefs_dir_ops *tracefs_ops = dentry->d_parent->d_fsdata; char *name; int ret; @@ -85,7 +86,7 @@ static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umo * mkdir routine to handle races. */ inode_unlock(inode); - ret = tracefs_ops.mkdir(name); + ret = tracefs_ops->mkdir(name); inode_lock(inode); kfree(name); @@ -95,6 +96,7 @@ static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umo static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry) { + struct tracefs_dir_ops *tracefs_ops = dentry->d_fsdata; char *name; int ret; @@ -112,7 +114,7 @@ static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry) inode_unlock(inode); inode_unlock(dentry->d_inode); - ret = tracefs_ops.rmdir(name); + ret = tracefs_ops->rmdir(name); inode_lock_nested(inode, I_MUTEX_PARENT); inode_lock(dentry->d_inode); @@ -342,6 +344,9 @@ static struct dentry *start_creating(const char *name, struct dentry *parent) if (IS_ERR(dentry)) { inode_unlock(parent->d_inode); simple_release_fs(&tracefs_mount, &tracefs_mount_count); + } else { + /* propagate dir ops */ + dentry->d_fsdata = parent->d_fsdata; } return dentry; @@ -482,18 +487,25 @@ struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *pare int (*mkdir)(const char *name), int (*rmdir)(const char *name)) { + struct tracefs_dir_ops *tracefs_ops = parent ? parent->d_fsdata : NULL; struct dentry *dentry; - /* Only allow one instance of the instances directory. */ - if (WARN_ON(tracefs_ops.mkdir || tracefs_ops.rmdir)) + if (WARN_ON(tracefs_ops)) + return NULL; + + tracefs_ops = kzalloc(sizeof(*tracefs_ops), GFP_KERNEL); + if (!tracefs_ops) return NULL; dentry = __create_dir(name, parent, &tracefs_dir_inode_operations); - if (!dentry) + if (!dentry) { + kfree(tracefs_ops); return NULL; + } - tracefs_ops.mkdir = mkdir; - tracefs_ops.rmdir = rmdir; + tracefs_ops->mkdir = mkdir; + tracefs_ops->rmdir = rmdir; + dentry->d_fsdata = tracefs_ops; return dentry; } @@ -513,8 +525,11 @@ static int __tracefs_remove(struct dentry *dentry, struct dentry *parent) simple_unlink(parent->d_inode, dentry); break; } - if (!ret) + if (!ret) { d_delete(dentry); + if (dentry->d_fsdata != parent->d_fsdata) + kfree(dentry->d_fsdata); + } dput(dentry); } } -- 2.14.1