All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vikas Shivappa <vikas.shivappa@linux.intel.com>
To: x86@kernel.org, linux-kernel@vger.kernel.org, tglx@linutronix.de
Cc: hpa@zytor.com, peterz@infradead.org, ravi.v.shankar@intel.com,
	vikas.shivappa@intel.com, tony.luck@intel.com,
	fenghua.yu@intel.com, andi.kleen@intel.com
Subject: [PATCH 11/21] x86/intel_rdt/cqm: Add mkdir support for RDT monitoring
Date: Mon, 26 Jun 2017 11:55:58 -0700	[thread overview]
Message-ID: <1498503368-20173-12-git-send-email-vikas.shivappa@linux.intel.com> (raw)
In-Reply-To: <1498503368-20173-1-git-send-email-vikas.shivappa@linux.intel.com>

Resource control groups can be created using mkdir in resctrl
fs(rdtgroup). In order to extend the resctrl interface to support
monitoring the control groups, extend the current mkdir to support
resource monitoring also.

This allows the rdtgroup created under the root directory to be able to
both control and monitor resources (ctrl_mon group). The ctrl_mon groups
are associated with one CLOSID like the legacy rdtgroups and one
RMID(Resource monitoring ID) as well. Hardware uses RMID to track the
resource usage. Once either of the CLOSID or RMID are exhausted, the
mkdir fails with -ENOSPC. If there are RMIDs in limbo list but not free
an -EBUSY is returned. User can also monitor a subset of the ctrl_mon
rdtgroup's tasks/cpus using the monitor groups. The monitor groups are
created using mkdir under the "mon_groups" directory in every ctrl_mon
group.

[Merged tony's code:
Removed a lot of common mkdir code, a fix to handling of the list of the
child rdtgroups and some cleanups in list traversal. Also the changes to
have similar alloc and free for CLOS/RMID and return -EBUSY when RMIDs
are in limbo and not free]

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Vikas Shivappa <vikas.shivappa@linux.intel.com>
---
 arch/x86/kernel/cpu/intel_rdt.h          |  17 +++
 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 201 ++++++++++++++++++++++++++-----
 2 files changed, 189 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/cpu/intel_rdt.h b/arch/x86/kernel/cpu/intel_rdt.h
index c0acfc3..fdf3654 100644
--- a/arch/x86/kernel/cpu/intel_rdt.h
+++ b/arch/x86/kernel/cpu/intel_rdt.h
@@ -37,23 +37,38 @@ struct mon_evt {
 extern bool rdt_alloc_enabled;
 extern int rdt_mon_features;
 
+enum rdt_group_type {
+	RDTCTRL_GROUP = 0,
+	RDTMON_GROUP,
+	RDT_NUM_GROUP,
+};
+
 /**
  * struct rdtgroup - store rdtgroup's data in resctrl file system.
  * @kn:				kernfs node
  * @rdtgroup_list:		linked list for all rdtgroups
+ * @parent:			parent rdtgrp
+ * @crdtgrp_list:		child rdtgroup node list
  * @closid:			closid for this rdtgroup
+ * @rmid:			rmid for this rdtgroup
  * @cpu_mask:			CPUs assigned to this rdtgroup
  * @flags:			status bits
  * @waitcount:			how many cpus expect to find this
  *				group when they acquire rdtgroup_mutex
+ * @type:			indicates type of this rdtgroup - either
+ *				monitor only or ctrl_mon group
  */
 struct rdtgroup {
 	struct kernfs_node	*kn;
 	struct list_head	rdtgroup_list;
+	struct rdtgroup		*parent;
+	struct list_head	crdtgrp_list;
 	int			closid;
+	u32			rmid;
 	struct cpumask		cpu_mask;
 	int			flags;
 	atomic_t		waitcount;
+	enum rdt_group_type	type;
 };
 
 /* rdtgroup.flags */
@@ -298,6 +313,8 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 				char *buf, size_t nbytes, loff_t off);
 int rdtgroup_schemata_show(struct kernfs_open_file *of,
 			   struct seq_file *s, void *v);
+int alloc_rmid(void);
+void free_rmid(u32 rmid);
 void rdt_get_mon_l3_config(struct rdt_resource *r);
 
 #endif /* _ASM_X86_INTEL_RDT_H */
diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
index e997330..36078c7 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -759,6 +759,39 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
 	return ret;
 }
 
+static int
+mongroup_create_dir(struct kernfs_node *parent_kn, struct rdtgroup *pr,
+		    char *name, struct kernfs_node **dest_kn)
+{
+	struct kernfs_node *kn;
+	int ret;
+
+	/* create the directory */
+	kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, pr);
+	if (IS_ERR(kn))
+		return PTR_ERR(kn);
+
+	if (dest_kn)
+		*dest_kn = kn;
+
+	/*
+	 * This extra ref will be put in kernfs_remove() and guarantees
+	 * that @rdtgrp->kn is always accessible.
+	 */
+	kernfs_get(kn);
+
+	ret = rdtgroup_kn_set_ugid(kn);
+	if (ret)
+		goto out_destroy;
+
+	kernfs_activate(kn);
+
+	return 0;
+
+out_destroy:
+	kernfs_remove(kn);
+	return ret;
+}
 static void l3_qos_cfg_update(void *arg)
 {
 	bool *enable = arg;
@@ -1083,43 +1116,38 @@ static void rdt_kill_sb(struct super_block *sb)
 	.kill_sb = rdt_kill_sb,
 };
 
-static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
-			  umode_t mode)
+/*
+ * Common code for ctrl_mon and monitor group mkdir.
+ * The caller needs to unlock the global mutex upon success.
+ */
+static int mkdir_rdt_common(struct kernfs_node *pkn, struct kernfs_node *prkn,
+			    const char *name, umode_t mode,
+			    enum rdt_group_type rtype, struct rdtgroup **r)
 {
-	struct rdtgroup *parent, *rdtgrp;
+	struct rdtgroup *prgrp, *rdtgrp;
 	struct kernfs_node *kn;
-	int ret, closid;
-
-	/* Only allow mkdir in the root directory */
-	if (parent_kn != rdtgroup_default.kn)
-		return -EPERM;
-
-	/* Do not accept '\n' to avoid unparsable situation. */
-	if (strchr(name, '\n'))
-		return -EINVAL;
+	uint fshift = 0;
+	int ret;
 
-	parent = rdtgroup_kn_lock_live(parent_kn);
-	if (!parent) {
+	prgrp = rdtgroup_kn_lock_live(prkn);
+	if (!prgrp) {
 		ret = -ENODEV;
 		goto out_unlock;
 	}
 
-	ret = closid_alloc();
-	if (ret < 0)
-		goto out_unlock;
-	closid = ret;
-
 	/* allocate the rdtgroup. */
 	rdtgrp = kzalloc(sizeof(*rdtgrp), GFP_KERNEL);
 	if (!rdtgrp) {
 		ret = -ENOSPC;
-		goto out_closid_free;
+		goto out_unlock;
 	}
-	rdtgrp->closid = closid;
-	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+	*r = rdtgrp;
+	rdtgrp->parent = prgrp;
+	rdtgrp->type = rtype;
+	INIT_LIST_HEAD(&rdtgrp->crdtgrp_list);
 
 	/* kernfs creates the directory for rdtgrp */
-	kn = kernfs_create_dir(parent->kn, name, mode, rdtgrp);
+	kn = kernfs_create_dir(pkn, name, mode, rdtgrp);
 	if (IS_ERR(kn)) {
 		ret = PTR_ERR(kn);
 		goto out_cancel_ref;
@@ -1138,27 +1166,138 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	if (ret)
 		goto out_destroy;
 
-	ret = rdtgroup_add_files(kn, RF_CTRL_BASE);
+	fshift = 1 << (RF_CTRLSHIFT + rtype);
+	ret = rdtgroup_add_files(kn, RFTYPE_BASE | fshift);
 	if (ret)
 		goto out_destroy;
 
+	if (rdt_mon_features) {
+		ret = alloc_rmid();
+		if (ret < 0)
+			return ret;
+
+		rdtgrp->rmid = ret;
+	}
 	kernfs_activate(kn);
 
-	ret = 0;
-	goto out_unlock;
+	return 0;
 
 out_destroy:
 	kernfs_remove(rdtgrp->kn);
 out_cancel_ref:
-	list_del(&rdtgrp->rdtgroup_list);
 	kfree(rdtgrp);
-out_closid_free:
+out_unlock:
+	rdtgroup_kn_unlock(prkn);
+	return ret;
+}
+
+static void mkdir_rdt_common_clean(struct rdtgroup *rgrp)
+{
+	kernfs_remove(rgrp->kn);
+	if (rgrp->rmid)
+		free_rmid(rgrp->rmid);
+	kfree(rgrp);
+}
+
+/*
+ * Create a monitor group under "mon_groups" directory of a control
+ * and monitor group(ctrl_mon). This is a resource group
+ * to monitor a subset of tasks and cpus in its parent ctrl_mon group.
+ */
+static int rdtgroup_mkdir_mon(struct kernfs_node *pkn, struct kernfs_node *prkn,
+			      const char *name,
+			      umode_t mode)
+{
+	struct rdtgroup *rdtgrp, *prdtgrp;
+	int ret;
+
+	ret = mkdir_rdt_common(pkn, prkn, name, mode, RDTMON_GROUP, &rdtgrp);
+	if (ret)
+		return ret;
+
+	prdtgrp = rdtgrp->parent;
+	rdtgrp->closid = prdtgrp->closid;
+
+	/*
+	 * Add the rdtgrp to the list of rdgrp the parent
+	 * ctrl_mon group has to track.
+	 */
+	list_add_tail(&rdtgrp->crdtgrp_list, &prdtgrp->crdtgrp_list);
+
+	rdtgroup_kn_unlock(prkn);
+	return ret;
+}
+
+/*
+ * These are rdtgroups created under the root directory. Can be used
+ * to allocate and monitor resources.
+ */
+static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *pkn,
+				   struct kernfs_node *prkn,
+				   const char *name, umode_t mode)
+{
+	struct rdtgroup *rdtgrp;
+	struct kernfs_node *kn;
+	int ret, closid;
+
+	ret = mkdir_rdt_common(pkn, prkn, name, mode, RDTCTRL_GROUP, &rdtgrp);
+	if (ret)
+		return ret;
+
+	kn = rdtgrp->kn;
+	ret = closid_alloc();
+	if (ret < 0)
+		goto out_common_fail;
+	closid = ret;
+
+	rdtgrp->closid = closid;
+	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+
+	if (rdt_mon_features) {
+		/*
+		 * Create an empty mon_groups directory to hold the subset
+		 * of tasks and cpus to monitor.
+		 */
+		ret = mongroup_create_dir(kn, NULL, "mon_groups", NULL);
+		if (ret)
+			goto out_id_free;
+	}
+
+	ret = 0;
+	goto out_unlock;
+
+out_id_free:
 	closid_free(closid);
+	list_del(&rdtgrp->rdtgroup_list);
+out_common_fail:
+	mkdir_rdt_common_clean(rdtgrp);
 out_unlock:
-	rdtgroup_kn_unlock(parent_kn);
+	rdtgroup_kn_unlock(prkn);
 	return ret;
 }
 
+static int rdtgroup_mkdir(struct kernfs_node *pkn, const char *name,
+			  umode_t mode)
+{
+	/* Do not accept '\n' to avoid unparsable situation. */
+	if (strchr(name, '\n'))
+		return -EINVAL;
+
+	/*
+	 * We don't allow rdtgroup ctrl_mon directories to be created anywhere
+	 * except the root directory and dont allow rdtgroup monitor
+	 * directories to be created anywhere execept inside mon_groups
+	 * directory.
+	 */
+	if (rdt_alloc_enabled && pkn == rdtgroup_default.kn)
+		return rdtgroup_mkdir_ctrl_mon(pkn, pkn, name, mode);
+	else if (rdt_mon_features &&
+		 !strcmp(pkn->name, "mon_groups"))
+		return rdtgroup_mkdir_mon(pkn, pkn->parent, name, mode);
+	else
+		return -EPERM;
+}
+
 static int rdtgroup_rmdir(struct kernfs_node *kn)
 {
 	int ret, cpu, closid = rdtgroup_default.closid;
@@ -1234,6 +1373,10 @@ static int __init rdtgroup_setup_root(void)
 	mutex_lock(&rdtgroup_mutex);
 
 	rdtgroup_default.closid = 0;
+	rdtgroup_default.rmid = 0;
+	rdtgroup_default.type = RDTCTRL_GROUP;
+	INIT_LIST_HEAD(&rdtgroup_default.crdtgrp_list);
+
 	list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);
 
 	ret = rdtgroup_add_files(rdt_root->kn, RF_CTRL_BASE);
-- 
1.9.1

  parent reply	other threads:[~2017-06-26 18:57 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-26 18:55 [PATCH V1 00/21] x86/cqm3: Resctrl based cqm Vikas Shivappa
2017-06-26 18:55 ` [PATCH 01/21] x86/perf/cqm: Wipe out perf " Vikas Shivappa
2017-06-26 18:55 ` [PATCH 02/21] x86/intel_rdt: Fix memory leak during mount Vikas Shivappa
2017-06-30 19:24   ` [tip:x86/urgent] x86/intel_rdt: Fix memory leak on mount failure tip-bot for Vikas Shivappa
2017-06-26 18:55 ` [PATCH 03/21] x86/intel_rdt/cqm: Documentation for resctrl based RDT Monitoring Vikas Shivappa
2017-06-26 18:55 ` [PATCH 04/21] x86/intel_rdt: Introduce a common compile option for RDT Vikas Shivappa
2017-06-26 18:55 ` [PATCH 05/21] x86/intel_rdt: Change file names to accommodate RDT monitor code Vikas Shivappa
2017-06-26 18:55 ` [PATCH 06/21] x86/intel_rdt: Cleanup namespace to support RDT monitoring Vikas Shivappa
2017-06-26 18:55 ` [PATCH 07/21] x86/intel_rdt/cqm: Add RDT monitoring initialization Vikas Shivappa
2017-07-02  9:14   ` Thomas Gleixner
2017-07-06 21:07     ` Shivappa Vikas
2017-06-26 18:55 ` [PATCH 08/21] x86/intel_rdt/cqm: Add RMID(Resource monitoring ID) management Vikas Shivappa
2017-07-02 10:05   ` Thomas Gleixner
2017-07-03  9:55     ` Thomas Gleixner
2017-07-05 15:34       ` Peter Zijlstra
2017-07-05 17:25         ` Thomas Gleixner
2017-07-11 23:54       ` Shivappa Vikas
2017-07-12 20:14         ` Thomas Gleixner
2017-07-05 17:59     ` Tony Luck
2017-07-06  6:51       ` Thomas Gleixner
2017-06-26 18:55 ` [PATCH 09/21] x86/intel_rdt: Simplify info and base file lists Vikas Shivappa
2017-07-02 10:09   ` Thomas Gleixner
2017-07-06 21:09     ` Shivappa Vikas
2017-06-26 18:55 ` [PATCH 10/21] x86/intel_rdt/cqm: Add info files for RDT monitoring Vikas Shivappa
2017-06-26 18:55 ` Vikas Shivappa [this message]
2017-07-02 10:58   ` [PATCH 11/21] x86/intel_rdt/cqm: Add mkdir support " Thomas Gleixner
2017-07-06 21:23     ` Shivappa Vikas
2017-06-26 18:55 ` [PATCH 12/21] x86/intel_rdt/cqm: Add tasks file support Vikas Shivappa
2017-07-02 11:01   ` Thomas Gleixner
2017-07-06 21:25     ` Shivappa Vikas
2017-06-26 18:56 ` [PATCH 13/21] x86/intel_rdt/cqm: Add cpus " Vikas Shivappa
2017-07-02 11:11   ` Thomas Gleixner
2017-07-06 21:26     ` Shivappa Vikas
2017-07-02 12:29   ` Thomas Gleixner
2017-07-06 21:42     ` Shivappa Vikas
2017-07-07  6:44       ` Thomas Gleixner
2017-07-13 18:37         ` Shivappa Vikas
2017-07-13 22:09     ` Shivappa Vikas
2017-06-26 18:56 ` [PATCH 14/21] x86/intel_rdt/cqm: Add mon_data Vikas Shivappa
2017-07-02 12:43   ` Thomas Gleixner
2017-07-06 21:48     ` Shivappa Vikas
2017-07-07  6:22       ` Thomas Gleixner
2017-07-11 21:17         ` Shivappa Vikas
2017-07-11 21:37           ` Luck, Tony
2017-06-26 18:56 ` [PATCH 15/21] x86/intel_rdt/cqm: Add rmdir support Vikas Shivappa
2017-07-02 13:16   ` Thomas Gleixner
2017-07-06 21:49     ` Shivappa Vikas
2017-06-26 18:56 ` [PATCH 16/21] x86/intel_rdt/cqm: Add mount,umount support Vikas Shivappa
2017-07-02 13:22   ` Thomas Gleixner
2017-07-06 21:58     ` Shivappa Vikas
2017-06-26 18:56 ` [PATCH 17/21] x86/intel_rdt/cqm: Add sched_in support Vikas Shivappa
2017-07-02 13:37   ` Thomas Gleixner
2017-07-06 23:35     ` Shivappa Vikas
2017-06-26 18:56 ` [PATCH 18/21] x86/intel_rdt/cqm: Add hotcpu support Vikas Shivappa
2017-06-26 18:56 ` [PATCH 19/21] x86/intel_rdt/mbm: Basic counting of MBM events (total and local) Vikas Shivappa
2017-07-02 13:46   ` Thomas Gleixner
2017-07-06 23:39     ` Shivappa Vikas
2017-07-07  6:47       ` Thomas Gleixner
2017-06-26 18:56 ` [PATCH 20/21] x86/intel_rdt/mbm: Add mbm counter initialization Vikas Shivappa
2017-06-26 18:56 ` [PATCH 21/21] x86/intel_rdt/mbm: Handle counter overflow Vikas Shivappa
2017-07-02 13:57   ` Thomas Gleixner
2017-07-06 23:53     ` Shivappa Vikas
2017-07-07  6:50       ` Thomas Gleixner
2017-07-10 17:54         ` Luck, Tony
2017-07-11 15:22           ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1498503368-20173-12-git-send-email-vikas.shivappa@linux.intel.com \
    --to=vikas.shivappa@linux.intel.com \
    --cc=andi.kleen@intel.com \
    --cc=fenghua.yu@intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=ravi.v.shankar@intel.com \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    --cc=vikas.shivappa@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.