[RFC,1/7] x86/resctrl: Add register/unregister functions for driver to hook into resctrl

Message ID 20230420220636.53527-2-tony.luck@intel.com
State New
Headers
Series Add driver registration i/f to resctrl |

Commit Message

Luck, Tony April 20, 2023, 10:06 p.m. UTC
  Just one callback at the point for the driver to be notified when the
resctrl filesystem is mounted or unmounted. Virtually all drivers
will need this hook to enable/disable their feature(s) as part of
mount/unmount.

Signed-off-by: Tony Luck <tony.luck@intel.com>
---
 include/linux/resctrl.h                | 13 +++++++
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 50 ++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
  

Comments

Reinette Chatre May 5, 2023, 11:17 p.m. UTC | #1
Hi Tony,

On 4/20/2023 3:06 PM, Tony Luck wrote:
> diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
> index 6ad33f355861..3e6778bde427 100644
> --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
> +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
> @@ -51,6 +51,9 @@ static struct kernfs_node *kn_mongrp;
>  /* Kernel fs node for "mon_data" directory under root */
>  static struct kernfs_node *kn_mondata;
>  
> +static LIST_HEAD(drivers);
> +static bool resctrl_is_mounted;
> +

fyi ...
https://lore.kernel.org/lkml/20230320172620.18254-13-james.morse@arm.com/

> +int resctrl_register_driver(struct resctrl_driver *d)
> +{
> +	mutex_lock(&rdtgroup_mutex);
> +	list_add(&d->list, &drivers);
> +
> +	if (resctrl_is_mounted)
> +		driver_up(d);
> +	mutex_unlock(&rdtgroup_mutex);
> +
> +	return 0;
> +}

Do you expect that the drivers may at any time
need to call into resctrl as opposed to relying entirely
on callbacks from resctrl? I am wondering about any potential
lock ordering issues between rdtgroup_mutex and locks
used internally by the drivers.

Reinette
  

Patch

diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 8334eeacfec5..78513edddca0 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -204,6 +204,19 @@  struct resctrl_schema {
 	u32				num_closid;
 };
 
+/**
+ * struct resctrl_driver - interface for driver to attach to resctrl
+ * @list:	List of registered drivers
+ * @mount:	Callback for mount/unmount
+ */
+struct resctrl_driver {
+	struct list_head	list;
+	void			(*mount)(bool mount);
+};
+
+int resctrl_register_driver(struct resctrl_driver *d);
+void resctrl_unregister_driver(struct resctrl_driver *d);
+
 /* The number of closid supported by this resource regardless of CDP */
 u32 resctrl_arch_get_num_closid(struct rdt_resource *r);
 int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid);
diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index 6ad33f355861..3e6778bde427 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -51,6 +51,9 @@  static struct kernfs_node *kn_mongrp;
 /* Kernel fs node for "mon_data" directory under root */
 static struct kernfs_node *kn_mondata;
 
+static LIST_HEAD(drivers);
+static bool resctrl_is_mounted;
+
 static struct seq_buf last_cmd_status;
 static char last_cmd_status_buf[512];
 
@@ -2437,6 +2440,42 @@  static int schemata_list_create(void)
 	return ret;
 }
 
+static void driver_up(struct resctrl_driver *d)
+{
+	if (d->mount)
+		d->mount(true);
+}
+
+static void driver_down(struct resctrl_driver *d)
+{
+	if (d->mount)
+		d->mount(false);
+}
+
+int resctrl_register_driver(struct resctrl_driver *d)
+{
+	mutex_lock(&rdtgroup_mutex);
+	list_add(&d->list, &drivers);
+
+	if (resctrl_is_mounted)
+		driver_up(d);
+	mutex_unlock(&rdtgroup_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(resctrl_register_driver);
+
+void resctrl_unregister_driver(struct resctrl_driver *d)
+{
+	mutex_lock(&rdtgroup_mutex);
+	list_del(&d->list);
+
+	if (resctrl_is_mounted)
+		driver_down(d);
+	mutex_unlock(&rdtgroup_mutex);
+}
+EXPORT_SYMBOL_GPL(resctrl_unregister_driver);
+
 static void schemata_list_destroy(void)
 {
 	struct resctrl_schema *s, *tmp;
@@ -2450,6 +2489,7 @@  static void schemata_list_destroy(void)
 static int rdt_get_tree(struct fs_context *fc)
 {
 	struct rdt_fs_context *ctx = rdt_fc2context(fc);
+	struct resctrl_driver *d;
 	struct rdt_domain *dom;
 	struct rdt_resource *r;
 	int ret;
@@ -2516,6 +2556,10 @@  static int rdt_get_tree(struct fs_context *fc)
 			mbm_setup_overflow_handler(dom, MBM_OVERFLOW_INTERVAL);
 	}
 
+	list_for_each_entry(d, &drivers, list)
+		driver_up(d);
+	resctrl_is_mounted = true;
+
 	goto out;
 
 out_psl:
@@ -2761,6 +2805,7 @@  static void rmdir_all_sub(void)
 
 static void rdt_kill_sb(struct super_block *sb)
 {
+	struct resctrl_driver *d;
 	struct rdt_resource *r;
 
 	cpus_read_lock();
@@ -2780,6 +2825,11 @@  static void rdt_kill_sb(struct super_block *sb)
 	static_branch_disable_cpuslocked(&rdt_mon_enable_key);
 	static_branch_disable_cpuslocked(&rdt_enable_key);
 	kernfs_kill_sb(sb);
+
+	list_for_each_entry(d, &drivers, list)
+		driver_down(d);
+	resctrl_is_mounted = false;
+
 	mutex_unlock(&rdtgroup_mutex);
 	cpus_read_unlock();
 }