mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
rv: Merge struct rv_monitor_def into struct rv_monitor
Each struct rv_monitor has a unique struct rv_monitor_def associated with it. struct rv_monitor is statically allocated, while struct rv_monitor_def is dynamically allocated. This makes the code more complicated than it should be: - Lookup is required to get the associated rv_monitor_def from rv_monitor - Dynamic memory allocation is required for rv_monitor_def. This is harder to get right compared to static memory. For instance, there is an existing mistake: rv_unregister_monitor() does not free the memory allocated by rv_register_monitor(). This is fortunately not a real memory leak problem, as rv_unregister_monitor() is never called. Simplify and merge rv_monitor_def into rv_monitor. Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://lore.kernel.org/194449c00f87945c207aab4c96920c75796a4f53.1753378331.git.namcao@linutronix.de Reviewed-by: Gabriele Monaco <gmonaco@redhat.com> Signed-off-by: Nam Cao <namcao@linutronix.de> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
b0c08dd534
commit
24cbfe18d5
@ -7,6 +7,9 @@
|
|||||||
#ifndef _LINUX_RV_H
|
#ifndef _LINUX_RV_H
|
||||||
#define _LINUX_RV_H
|
#define _LINUX_RV_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
|
||||||
#define MAX_DA_NAME_LEN 32
|
#define MAX_DA_NAME_LEN 32
|
||||||
|
|
||||||
#ifdef CONFIG_RV
|
#ifdef CONFIG_RV
|
||||||
@ -98,8 +101,13 @@ struct rv_monitor {
|
|||||||
void (*disable)(void);
|
void (*disable)(void);
|
||||||
void (*reset)(void);
|
void (*reset)(void);
|
||||||
#ifdef CONFIG_RV_REACTORS
|
#ifdef CONFIG_RV_REACTORS
|
||||||
|
struct rv_reactor_def *rdef;
|
||||||
__printf(1, 2) void (*react)(const char *msg, ...);
|
__printf(1, 2) void (*react)(const char *msg, ...);
|
||||||
|
bool reacting;
|
||||||
#endif
|
#endif
|
||||||
|
struct list_head list;
|
||||||
|
struct rv_monitor *parent;
|
||||||
|
struct dentry *root_d;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool rv_monitoring_on(void);
|
bool rv_monitoring_on(void);
|
||||||
|
@ -210,9 +210,9 @@ void rv_put_task_monitor_slot(int slot)
|
|||||||
* Monitors with a parent are nested,
|
* Monitors with a parent are nested,
|
||||||
* Monitors without a parent could be standalone or containers.
|
* Monitors without a parent could be standalone or containers.
|
||||||
*/
|
*/
|
||||||
bool rv_is_nested_monitor(struct rv_monitor_def *mdef)
|
bool rv_is_nested_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
return mdef->parent != NULL;
|
return mon->parent != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -223,16 +223,16 @@ bool rv_is_nested_monitor(struct rv_monitor_def *mdef)
|
|||||||
* for enable()/disable(). Use this condition to find empty containers.
|
* for enable()/disable(). Use this condition to find empty containers.
|
||||||
* Keep both conditions in case we have some non-compliant containers.
|
* Keep both conditions in case we have some non-compliant containers.
|
||||||
*/
|
*/
|
||||||
bool rv_is_container_monitor(struct rv_monitor_def *mdef)
|
bool rv_is_container_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *next;
|
struct rv_monitor *next;
|
||||||
|
|
||||||
if (list_is_last(&mdef->list, &rv_monitors_list))
|
if (list_is_last(&mon->list, &rv_monitors_list))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
next = list_next_entry(mdef, list);
|
next = list_next_entry(mon, list);
|
||||||
|
|
||||||
return next->parent == mdef->monitor || !mdef->monitor->enable;
|
return next->parent == mon || !mon->enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -241,10 +241,10 @@ bool rv_is_container_monitor(struct rv_monitor_def *mdef)
|
|||||||
static ssize_t monitor_enable_read_data(struct file *filp, char __user *user_buf, size_t count,
|
static ssize_t monitor_enable_read_data(struct file *filp, char __user *user_buf, size_t count,
|
||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef = filp->private_data;
|
struct rv_monitor *mon = filp->private_data;
|
||||||
const char *buff;
|
const char *buff;
|
||||||
|
|
||||||
buff = mdef->monitor->enabled ? "1\n" : "0\n";
|
buff = mon->enabled ? "1\n" : "0\n";
|
||||||
|
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
|
return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
|
||||||
}
|
}
|
||||||
@ -252,14 +252,14 @@ static ssize_t monitor_enable_read_data(struct file *filp, char __user *user_buf
|
|||||||
/*
|
/*
|
||||||
* __rv_disable_monitor - disabled an enabled monitor
|
* __rv_disable_monitor - disabled an enabled monitor
|
||||||
*/
|
*/
|
||||||
static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
|
static int __rv_disable_monitor(struct rv_monitor *mon, bool sync)
|
||||||
{
|
{
|
||||||
lockdep_assert_held(&rv_interface_lock);
|
lockdep_assert_held(&rv_interface_lock);
|
||||||
|
|
||||||
if (mdef->monitor->enabled) {
|
if (mon->enabled) {
|
||||||
mdef->monitor->enabled = 0;
|
mon->enabled = 0;
|
||||||
if (mdef->monitor->disable)
|
if (mon->disable)
|
||||||
mdef->monitor->disable();
|
mon->disable();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for the execution of all events to finish.
|
* Wait for the execution of all events to finish.
|
||||||
@ -273,90 +273,90 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rv_disable_single(struct rv_monitor_def *mdef)
|
static void rv_disable_single(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
__rv_disable_monitor(mdef, true);
|
__rv_disable_monitor(mon, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rv_enable_single(struct rv_monitor_def *mdef)
|
static int rv_enable_single(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
lockdep_assert_held(&rv_interface_lock);
|
lockdep_assert_held(&rv_interface_lock);
|
||||||
|
|
||||||
if (mdef->monitor->enabled)
|
if (mon->enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
retval = mdef->monitor->enable();
|
retval = mon->enable();
|
||||||
|
|
||||||
if (!retval)
|
if (!retval)
|
||||||
mdef->monitor->enabled = 1;
|
mon->enabled = 1;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rv_disable_container(struct rv_monitor_def *mdef)
|
static void rv_disable_container(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *p = mdef;
|
struct rv_monitor *p = mon;
|
||||||
int enabled = 0;
|
int enabled = 0;
|
||||||
|
|
||||||
list_for_each_entry_continue(p, &rv_monitors_list, list) {
|
list_for_each_entry_continue(p, &rv_monitors_list, list) {
|
||||||
if (p->parent != mdef->monitor)
|
if (p->parent != mon)
|
||||||
break;
|
break;
|
||||||
enabled += __rv_disable_monitor(p, false);
|
enabled += __rv_disable_monitor(p, false);
|
||||||
}
|
}
|
||||||
if (enabled)
|
if (enabled)
|
||||||
tracepoint_synchronize_unregister();
|
tracepoint_synchronize_unregister();
|
||||||
mdef->monitor->enabled = 0;
|
mon->enabled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rv_enable_container(struct rv_monitor_def *mdef)
|
static int rv_enable_container(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *p = mdef;
|
struct rv_monitor *p = mon;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
list_for_each_entry_continue(p, &rv_monitors_list, list) {
|
list_for_each_entry_continue(p, &rv_monitors_list, list) {
|
||||||
if (retval || p->parent != mdef->monitor)
|
if (retval || p->parent != mon)
|
||||||
break;
|
break;
|
||||||
retval = rv_enable_single(p);
|
retval = rv_enable_single(p);
|
||||||
}
|
}
|
||||||
if (retval)
|
if (retval)
|
||||||
rv_disable_container(mdef);
|
rv_disable_container(mon);
|
||||||
else
|
else
|
||||||
mdef->monitor->enabled = 1;
|
mon->enabled = 1;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rv_disable_monitor - disable a given runtime monitor
|
* rv_disable_monitor - disable a given runtime monitor
|
||||||
* @mdef: Pointer to the monitor definition structure.
|
* @mon: Pointer to the monitor definition structure.
|
||||||
*
|
*
|
||||||
* Returns 0 on success.
|
* Returns 0 on success.
|
||||||
*/
|
*/
|
||||||
int rv_disable_monitor(struct rv_monitor_def *mdef)
|
int rv_disable_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
if (rv_is_container_monitor(mdef))
|
if (rv_is_container_monitor(mon))
|
||||||
rv_disable_container(mdef);
|
rv_disable_container(mon);
|
||||||
else
|
else
|
||||||
rv_disable_single(mdef);
|
rv_disable_single(mon);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rv_enable_monitor - enable a given runtime monitor
|
* rv_enable_monitor - enable a given runtime monitor
|
||||||
* @mdef: Pointer to the monitor definition structure.
|
* @mon: Pointer to the monitor definition structure.
|
||||||
*
|
*
|
||||||
* Returns 0 on success, error otherwise.
|
* Returns 0 on success, error otherwise.
|
||||||
*/
|
*/
|
||||||
int rv_enable_monitor(struct rv_monitor_def *mdef)
|
int rv_enable_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (rv_is_container_monitor(mdef))
|
if (rv_is_container_monitor(mon))
|
||||||
retval = rv_enable_container(mdef);
|
retval = rv_enable_container(mon);
|
||||||
else
|
else
|
||||||
retval = rv_enable_single(mdef);
|
retval = rv_enable_single(mon);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -367,7 +367,7 @@ int rv_enable_monitor(struct rv_monitor_def *mdef)
|
|||||||
static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
|
static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef = filp->private_data;
|
struct rv_monitor *mon = filp->private_data;
|
||||||
int retval;
|
int retval;
|
||||||
bool val;
|
bool val;
|
||||||
|
|
||||||
@ -378,9 +378,9 @@ static ssize_t monitor_enable_write_data(struct file *filp, const char __user *u
|
|||||||
mutex_lock(&rv_interface_lock);
|
mutex_lock(&rv_interface_lock);
|
||||||
|
|
||||||
if (val)
|
if (val)
|
||||||
retval = rv_enable_monitor(mdef);
|
retval = rv_enable_monitor(mon);
|
||||||
else
|
else
|
||||||
retval = rv_disable_monitor(mdef);
|
retval = rv_disable_monitor(mon);
|
||||||
|
|
||||||
mutex_unlock(&rv_interface_lock);
|
mutex_unlock(&rv_interface_lock);
|
||||||
|
|
||||||
@ -399,12 +399,12 @@ static const struct file_operations interface_enable_fops = {
|
|||||||
static ssize_t monitor_desc_read_data(struct file *filp, char __user *user_buf, size_t count,
|
static ssize_t monitor_desc_read_data(struct file *filp, char __user *user_buf, size_t count,
|
||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef = filp->private_data;
|
struct rv_monitor *mon = filp->private_data;
|
||||||
char buff[256];
|
char buff[256];
|
||||||
|
|
||||||
memset(buff, 0, sizeof(buff));
|
memset(buff, 0, sizeof(buff));
|
||||||
|
|
||||||
snprintf(buff, sizeof(buff), "%s\n", mdef->monitor->description);
|
snprintf(buff, sizeof(buff), "%s\n", mon->description);
|
||||||
|
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff) + 1);
|
return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff) + 1);
|
||||||
}
|
}
|
||||||
@ -419,37 +419,37 @@ static const struct file_operations interface_desc_fops = {
|
|||||||
* the monitor dir, where the specific options of the monitor
|
* the monitor dir, where the specific options of the monitor
|
||||||
* are exposed.
|
* are exposed.
|
||||||
*/
|
*/
|
||||||
static int create_monitor_dir(struct rv_monitor_def *mdef, struct rv_monitor_def *parent)
|
static int create_monitor_dir(struct rv_monitor *mon, struct rv_monitor *parent)
|
||||||
{
|
{
|
||||||
struct dentry *root = parent ? parent->root_d : get_monitors_root();
|
struct dentry *root = parent ? parent->root_d : get_monitors_root();
|
||||||
const char *name = mdef->monitor->name;
|
const char *name = mon->name;
|
||||||
struct dentry *tmp;
|
struct dentry *tmp;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
mdef->root_d = rv_create_dir(name, root);
|
mon->root_d = rv_create_dir(name, root);
|
||||||
if (!mdef->root_d)
|
if (!mon->root_d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
tmp = rv_create_file("enable", RV_MODE_WRITE, mdef->root_d, mdef, &interface_enable_fops);
|
tmp = rv_create_file("enable", RV_MODE_WRITE, mon->root_d, mon, &interface_enable_fops);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto out_remove_root;
|
goto out_remove_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = rv_create_file("desc", RV_MODE_READ, mdef->root_d, mdef, &interface_desc_fops);
|
tmp = rv_create_file("desc", RV_MODE_READ, mon->root_d, mon, &interface_desc_fops);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto out_remove_root;
|
goto out_remove_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = reactor_populate_monitor(mdef);
|
retval = reactor_populate_monitor(mon);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out_remove_root;
|
goto out_remove_root;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_remove_root:
|
out_remove_root:
|
||||||
rv_remove(mdef->root_d);
|
rv_remove(mon->root_d);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,13 +458,12 @@ out_remove_root:
|
|||||||
*/
|
*/
|
||||||
static int monitors_show(struct seq_file *m, void *p)
|
static int monitors_show(struct seq_file *m, void *p)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mon_def = p;
|
struct rv_monitor *mon = p;
|
||||||
|
|
||||||
if (mon_def->parent)
|
if (mon->parent)
|
||||||
seq_printf(m, "%s:%s\n", mon_def->parent->name,
|
seq_printf(m, "%s:%s\n", mon->parent->name, mon->name);
|
||||||
mon_def->monitor->name);
|
|
||||||
else
|
else
|
||||||
seq_printf(m, "%s\n", mon_def->monitor->name);
|
seq_printf(m, "%s\n", mon->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,13 +495,13 @@ static void *available_monitors_next(struct seq_file *m, void *p, loff_t *pos)
|
|||||||
*/
|
*/
|
||||||
static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos)
|
static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *m_def = p;
|
struct rv_monitor *mon = p;
|
||||||
|
|
||||||
(*pos)++;
|
(*pos)++;
|
||||||
|
|
||||||
list_for_each_entry_continue(m_def, &rv_monitors_list, list) {
|
list_for_each_entry_continue(mon, &rv_monitors_list, list) {
|
||||||
if (m_def->monitor->enabled)
|
if (mon->enabled)
|
||||||
return m_def;
|
return mon;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -510,7 +509,7 @@ static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos)
|
|||||||
|
|
||||||
static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
|
static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *m_def;
|
struct rv_monitor *mon;
|
||||||
loff_t l;
|
loff_t l;
|
||||||
|
|
||||||
mutex_lock(&rv_interface_lock);
|
mutex_lock(&rv_interface_lock);
|
||||||
@ -518,15 +517,15 @@ static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
|
|||||||
if (list_empty(&rv_monitors_list))
|
if (list_empty(&rv_monitors_list))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
m_def = list_entry(&rv_monitors_list, struct rv_monitor_def, list);
|
mon = list_entry(&rv_monitors_list, struct rv_monitor, list);
|
||||||
|
|
||||||
for (l = 0; l <= *pos; ) {
|
for (l = 0; l <= *pos; ) {
|
||||||
m_def = enabled_monitors_next(m, m_def, &l);
|
mon = enabled_monitors_next(m, mon, &l);
|
||||||
if (!m_def)
|
if (!mon)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_def;
|
return mon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -566,13 +565,13 @@ static const struct file_operations available_monitors_ops = {
|
|||||||
*/
|
*/
|
||||||
static void disable_all_monitors(void)
|
static void disable_all_monitors(void)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef;
|
struct rv_monitor *mon;
|
||||||
int enabled = 0;
|
int enabled = 0;
|
||||||
|
|
||||||
mutex_lock(&rv_interface_lock);
|
mutex_lock(&rv_interface_lock);
|
||||||
|
|
||||||
list_for_each_entry(mdef, &rv_monitors_list, list)
|
list_for_each_entry(mon, &rv_monitors_list, list)
|
||||||
enabled += __rv_disable_monitor(mdef, false);
|
enabled += __rv_disable_monitor(mon, false);
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
/*
|
/*
|
||||||
@ -598,7 +597,7 @@ static ssize_t enabled_monitors_write(struct file *filp, const char __user *user
|
|||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
|
char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
|
||||||
struct rv_monitor_def *mdef;
|
struct rv_monitor *mon;
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
bool enable = true;
|
bool enable = true;
|
||||||
char *ptr, *tmp;
|
char *ptr, *tmp;
|
||||||
@ -633,17 +632,17 @@ static ssize_t enabled_monitors_write(struct file *filp, const char __user *user
|
|||||||
if (tmp)
|
if (tmp)
|
||||||
ptr = tmp+1;
|
ptr = tmp+1;
|
||||||
|
|
||||||
list_for_each_entry(mdef, &rv_monitors_list, list) {
|
list_for_each_entry(mon, &rv_monitors_list, list) {
|
||||||
if (strcmp(ptr, mdef->monitor->name) != 0)
|
if (strcmp(ptr, mon->name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Monitor found!
|
* Monitor found!
|
||||||
*/
|
*/
|
||||||
if (enable)
|
if (enable)
|
||||||
retval = rv_enable_monitor(mdef);
|
retval = rv_enable_monitor(mon);
|
||||||
else
|
else
|
||||||
retval = rv_disable_monitor(mdef);
|
retval = rv_disable_monitor(mon);
|
||||||
|
|
||||||
if (!retval)
|
if (!retval)
|
||||||
retval = count;
|
retval = count;
|
||||||
@ -702,11 +701,11 @@ static void turn_monitoring_off(void)
|
|||||||
|
|
||||||
static void reset_all_monitors(void)
|
static void reset_all_monitors(void)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef;
|
struct rv_monitor *mon;
|
||||||
|
|
||||||
list_for_each_entry(mdef, &rv_monitors_list, list) {
|
list_for_each_entry(mon, &rv_monitors_list, list) {
|
||||||
if (mdef->monitor->enabled && mdef->monitor->reset)
|
if (mon->enabled && mon->reset)
|
||||||
mdef->monitor->reset();
|
mon->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,10 +767,10 @@ static const struct file_operations monitoring_on_fops = {
|
|||||||
.read = monitoring_on_read_data,
|
.read = monitoring_on_read_data,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void destroy_monitor_dir(struct rv_monitor_def *mdef)
|
static void destroy_monitor_dir(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
reactor_cleanup_monitor(mdef);
|
reactor_cleanup_monitor(mon);
|
||||||
rv_remove(mdef->root_d);
|
rv_remove(mon->root_d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -783,7 +782,7 @@ static void destroy_monitor_dir(struct rv_monitor_def *mdef)
|
|||||||
*/
|
*/
|
||||||
int rv_register_monitor(struct rv_monitor *monitor, struct rv_monitor *parent)
|
int rv_register_monitor(struct rv_monitor *monitor, struct rv_monitor *parent)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *r, *p = NULL;
|
struct rv_monitor *r;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (strlen(monitor->name) >= MAX_RV_MONITOR_NAME_SIZE) {
|
if (strlen(monitor->name) >= MAX_RV_MONITOR_NAME_SIZE) {
|
||||||
@ -795,49 +794,31 @@ int rv_register_monitor(struct rv_monitor *monitor, struct rv_monitor *parent)
|
|||||||
mutex_lock(&rv_interface_lock);
|
mutex_lock(&rv_interface_lock);
|
||||||
|
|
||||||
list_for_each_entry(r, &rv_monitors_list, list) {
|
list_for_each_entry(r, &rv_monitors_list, list) {
|
||||||
if (strcmp(monitor->name, r->monitor->name) == 0) {
|
if (strcmp(monitor->name, r->name) == 0) {
|
||||||
pr_info("Monitor %s is already registered\n", monitor->name);
|
pr_info("Monitor %s is already registered\n", monitor->name);
|
||||||
retval = -EEXIST;
|
retval = -EEXIST;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent) {
|
if (parent && rv_is_nested_monitor(parent)) {
|
||||||
list_for_each_entry(r, &rv_monitors_list, list) {
|
|
||||||
if (strcmp(parent->name, r->monitor->name) == 0) {
|
|
||||||
p = r;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p && rv_is_nested_monitor(p)) {
|
|
||||||
pr_info("Parent monitor %s is already nested, cannot nest further\n",
|
pr_info("Parent monitor %s is already nested, cannot nest further\n",
|
||||||
parent->name);
|
parent->name);
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = kzalloc(sizeof(struct rv_monitor_def), GFP_KERNEL);
|
monitor->parent = parent;
|
||||||
if (!r) {
|
|
||||||
retval = -ENOMEM;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->monitor = monitor;
|
retval = create_monitor_dir(monitor, parent);
|
||||||
r->parent = parent;
|
if (retval)
|
||||||
|
return retval;
|
||||||
retval = create_monitor_dir(r, p);
|
|
||||||
if (retval) {
|
|
||||||
kfree(r);
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keep children close to the parent for easier visualisation */
|
/* keep children close to the parent for easier visualisation */
|
||||||
if (p)
|
if (parent)
|
||||||
list_add(&r->list, &p->list);
|
list_add(&monitor->list, &parent->list);
|
||||||
else
|
else
|
||||||
list_add_tail(&r->list, &rv_monitors_list);
|
list_add_tail(&monitor->list, &rv_monitors_list);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&rv_interface_lock);
|
mutex_unlock(&rv_interface_lock);
|
||||||
@ -852,17 +833,11 @@ out_unlock:
|
|||||||
*/
|
*/
|
||||||
int rv_unregister_monitor(struct rv_monitor *monitor)
|
int rv_unregister_monitor(struct rv_monitor *monitor)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *ptr, *next;
|
|
||||||
|
|
||||||
mutex_lock(&rv_interface_lock);
|
mutex_lock(&rv_interface_lock);
|
||||||
|
|
||||||
list_for_each_entry_safe(ptr, next, &rv_monitors_list, list) {
|
rv_disable_monitor(monitor);
|
||||||
if (strcmp(monitor->name, ptr->monitor->name) == 0) {
|
list_del(&monitor->list);
|
||||||
rv_disable_monitor(ptr);
|
destroy_monitor_dir(monitor);
|
||||||
list_del(&ptr->list);
|
|
||||||
destroy_monitor_dir(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&rv_interface_lock);
|
mutex_unlock(&rv_interface_lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -32,34 +32,23 @@ struct rv_reactor_def {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct rv_monitor_def {
|
|
||||||
struct list_head list;
|
|
||||||
struct rv_monitor *monitor;
|
|
||||||
struct rv_monitor *parent;
|
|
||||||
struct dentry *root_d;
|
|
||||||
#ifdef CONFIG_RV_REACTORS
|
|
||||||
struct rv_reactor_def *rdef;
|
|
||||||
bool reacting;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dentry *get_monitors_root(void);
|
struct dentry *get_monitors_root(void);
|
||||||
int rv_disable_monitor(struct rv_monitor_def *mdef);
|
int rv_disable_monitor(struct rv_monitor *mon);
|
||||||
int rv_enable_monitor(struct rv_monitor_def *mdef);
|
int rv_enable_monitor(struct rv_monitor *mon);
|
||||||
bool rv_is_container_monitor(struct rv_monitor_def *mdef);
|
bool rv_is_container_monitor(struct rv_monitor *mon);
|
||||||
bool rv_is_nested_monitor(struct rv_monitor_def *mdef);
|
bool rv_is_nested_monitor(struct rv_monitor *mon);
|
||||||
|
|
||||||
#ifdef CONFIG_RV_REACTORS
|
#ifdef CONFIG_RV_REACTORS
|
||||||
int reactor_populate_monitor(struct rv_monitor_def *mdef);
|
int reactor_populate_monitor(struct rv_monitor *mon);
|
||||||
void reactor_cleanup_monitor(struct rv_monitor_def *mdef);
|
void reactor_cleanup_monitor(struct rv_monitor *mon);
|
||||||
int init_rv_reactors(struct dentry *root_dir);
|
int init_rv_reactors(struct dentry *root_dir);
|
||||||
#else
|
#else
|
||||||
static inline int reactor_populate_monitor(struct rv_monitor_def *mdef)
|
static inline int reactor_populate_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reactor_cleanup_monitor(struct rv_monitor_def *mdef)
|
static inline void reactor_cleanup_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -138,10 +138,10 @@ static const struct file_operations available_reactors_ops = {
|
|||||||
*/
|
*/
|
||||||
static int monitor_reactor_show(struct seq_file *m, void *p)
|
static int monitor_reactor_show(struct seq_file *m, void *p)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef = m->private;
|
struct rv_monitor *mon = m->private;
|
||||||
struct rv_reactor_def *rdef = p;
|
struct rv_reactor_def *rdef = p;
|
||||||
|
|
||||||
if (mdef->rdef == rdef)
|
if (mon->rdef == rdef)
|
||||||
seq_printf(m, "[%s]\n", rdef->reactor->name);
|
seq_printf(m, "[%s]\n", rdef->reactor->name);
|
||||||
else
|
else
|
||||||
seq_printf(m, "%s\n", rdef->reactor->name);
|
seq_printf(m, "%s\n", rdef->reactor->name);
|
||||||
@ -158,41 +158,41 @@ static const struct seq_operations monitor_reactors_seq_ops = {
|
|||||||
.show = monitor_reactor_show
|
.show = monitor_reactor_show
|
||||||
};
|
};
|
||||||
|
|
||||||
static void monitor_swap_reactors_single(struct rv_monitor_def *mdef,
|
static void monitor_swap_reactors_single(struct rv_monitor *mon,
|
||||||
struct rv_reactor_def *rdef,
|
struct rv_reactor_def *rdef,
|
||||||
bool reacting, bool nested)
|
bool reacting, bool nested)
|
||||||
{
|
{
|
||||||
bool monitor_enabled;
|
bool monitor_enabled;
|
||||||
|
|
||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
if (mdef->rdef == rdef)
|
if (mon->rdef == rdef)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
monitor_enabled = mdef->monitor->enabled;
|
monitor_enabled = mon->enabled;
|
||||||
if (monitor_enabled)
|
if (monitor_enabled)
|
||||||
rv_disable_monitor(mdef);
|
rv_disable_monitor(mon);
|
||||||
|
|
||||||
/* swap reactor's usage */
|
/* swap reactor's usage */
|
||||||
mdef->rdef->counter--;
|
mon->rdef->counter--;
|
||||||
rdef->counter++;
|
rdef->counter++;
|
||||||
|
|
||||||
mdef->rdef = rdef;
|
mon->rdef = rdef;
|
||||||
mdef->reacting = reacting;
|
mon->reacting = reacting;
|
||||||
mdef->monitor->react = rdef->reactor->react;
|
mon->react = rdef->reactor->react;
|
||||||
|
|
||||||
/* enable only once if iterating through a container */
|
/* enable only once if iterating through a container */
|
||||||
if (monitor_enabled && !nested)
|
if (monitor_enabled && !nested)
|
||||||
rv_enable_monitor(mdef);
|
rv_enable_monitor(mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_swap_reactors(struct rv_monitor_def *mdef,
|
static void monitor_swap_reactors(struct rv_monitor *mon,
|
||||||
struct rv_reactor_def *rdef, bool reacting)
|
struct rv_reactor_def *rdef, bool reacting)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *p = mdef;
|
struct rv_monitor *p = mon;
|
||||||
|
|
||||||
if (rv_is_container_monitor(mdef))
|
if (rv_is_container_monitor(mon))
|
||||||
list_for_each_entry_continue(p, &rv_monitors_list, list) {
|
list_for_each_entry_continue(p, &rv_monitors_list, list) {
|
||||||
if (p->parent != mdef->monitor)
|
if (p->parent != mon)
|
||||||
break;
|
break;
|
||||||
monitor_swap_reactors_single(p, rdef, reacting, true);
|
monitor_swap_reactors_single(p, rdef, reacting, true);
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ static void monitor_swap_reactors(struct rv_monitor_def *mdef,
|
|||||||
* All nested monitors are enabled also if they were off, we may refine
|
* All nested monitors are enabled also if they were off, we may refine
|
||||||
* this logic in the future.
|
* this logic in the future.
|
||||||
*/
|
*/
|
||||||
monitor_swap_reactors_single(mdef, rdef, reacting, false);
|
monitor_swap_reactors_single(mon, rdef, reacting, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
@ -210,7 +210,7 @@ monitor_reactors_write(struct file *file, const char __user *user_buf,
|
|||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
char buff[MAX_RV_REACTOR_NAME_SIZE + 2];
|
char buff[MAX_RV_REACTOR_NAME_SIZE + 2];
|
||||||
struct rv_monitor_def *mdef;
|
struct rv_monitor *mon;
|
||||||
struct rv_reactor_def *rdef;
|
struct rv_reactor_def *rdef;
|
||||||
struct seq_file *seq_f;
|
struct seq_file *seq_f;
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
@ -237,7 +237,7 @@ monitor_reactors_write(struct file *file, const char __user *user_buf,
|
|||||||
* See monitor_reactors_open()
|
* See monitor_reactors_open()
|
||||||
*/
|
*/
|
||||||
seq_f = file->private_data;
|
seq_f = file->private_data;
|
||||||
mdef = seq_f->private;
|
mon = seq_f->private;
|
||||||
|
|
||||||
mutex_lock(&rv_interface_lock);
|
mutex_lock(&rv_interface_lock);
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ monitor_reactors_write(struct file *file, const char __user *user_buf,
|
|||||||
else
|
else
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
monitor_swap_reactors(mdef, rdef, enable);
|
monitor_swap_reactors(mon, rdef, enable);
|
||||||
|
|
||||||
retval = count;
|
retval = count;
|
||||||
break;
|
break;
|
||||||
@ -268,7 +268,7 @@ monitor_reactors_write(struct file *file, const char __user *user_buf,
|
|||||||
*/
|
*/
|
||||||
static int monitor_reactors_open(struct inode *inode, struct file *file)
|
static int monitor_reactors_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct rv_monitor_def *mdef = inode->i_private;
|
struct rv_monitor *mon = inode->i_private;
|
||||||
struct seq_file *seq_f;
|
struct seq_file *seq_f;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ static int monitor_reactors_open(struct inode *inode, struct file *file)
|
|||||||
/*
|
/*
|
||||||
* Copy the create file "private" data to the seq_file private data.
|
* Copy the create file "private" data to the seq_file private data.
|
||||||
*/
|
*/
|
||||||
seq_f->private = mdef;
|
seq_f->private = mon;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@ -454,37 +454,37 @@ static const struct file_operations reacting_on_fops = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* reactor_populate_monitor - creates per monitor reactors file
|
* reactor_populate_monitor - creates per monitor reactors file
|
||||||
* @mdef: monitor's definition.
|
* @mon: The monitor.
|
||||||
*
|
*
|
||||||
* Returns 0 if successful, error otherwise.
|
* Returns 0 if successful, error otherwise.
|
||||||
*/
|
*/
|
||||||
int reactor_populate_monitor(struct rv_monitor_def *mdef)
|
int reactor_populate_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
struct dentry *tmp;
|
struct dentry *tmp;
|
||||||
|
|
||||||
tmp = rv_create_file("reactors", RV_MODE_WRITE, mdef->root_d, mdef, &monitor_reactors_ops);
|
tmp = rv_create_file("reactors", RV_MODE_WRITE, mon->root_d, mon, &monitor_reactors_ops);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure as the rv_nop reactor.
|
* Configure as the rv_nop reactor.
|
||||||
*/
|
*/
|
||||||
mdef->rdef = get_reactor_rdef_by_name("nop");
|
mon->rdef = get_reactor_rdef_by_name("nop");
|
||||||
mdef->rdef->counter++;
|
mon->rdef->counter++;
|
||||||
mdef->reacting = false;
|
mon->reacting = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reactor_cleanup_monitor - cleanup a monitor reference
|
* reactor_cleanup_monitor - cleanup a monitor reference
|
||||||
* @mdef: monitor's definition.
|
* @mon: the monitor.
|
||||||
*/
|
*/
|
||||||
void reactor_cleanup_monitor(struct rv_monitor_def *mdef)
|
void reactor_cleanup_monitor(struct rv_monitor *mon)
|
||||||
{
|
{
|
||||||
lockdep_assert_held(&rv_interface_lock);
|
lockdep_assert_held(&rv_interface_lock);
|
||||||
mdef->rdef->counter--;
|
mon->rdef->counter--;
|
||||||
WARN_ON_ONCE(mdef->rdef->counter < 0);
|
WARN_ON_ONCE(mon->rdef->counter < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user