From: Wei Li <[email protected]> The reactor swap inlines the disable-update-re-enable pattern in monitor_swap_reactors_single(). The nested flag splits one helper into two behaviors. The container path re-enables every nested monitor, including the ones the user left off. This abnormal logic seems to be a temporary strategy from the comments.
Add rv_update_monitor() helper with callback for generic update processing. A monitor is updated with it quiesced and keeps its enabled state, including the children of a container. Signed-off-by: Wei Li <[email protected]> --- kernel/trace/rv/rv.c | 49 +++++++++++++++++++++++++++++++++++ kernel/trace/rv/rv.h | 2 ++ kernel/trace/rv/rv_reactors.c | 34 +++++------------------- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c index 29f155c6968b..4e689d4590ae 100644 --- a/kernel/trace/rv/rv.c +++ b/kernel/trace/rv/rv.c @@ -289,6 +289,19 @@ static int rv_enable_single(struct rv_monitor *mon) return retval; } +static int rv_update_single(struct rv_monitor *mon, rvmon_update_fn_t update, void *data) +{ + int retval = 0; + int enabled; + + enabled = __rv_disable_monitor(mon, true); + update(mon, data); + if (enabled) + retval = rv_enable_single(mon); + + return retval; +} + static void rv_disable_container(struct rv_monitor *mon) { struct rv_monitor *p = mon; @@ -321,6 +334,22 @@ static int rv_enable_container(struct rv_monitor *mon) return retval; } +static int rv_update_container(struct rv_monitor *mon, rvmon_update_fn_t update, void *data) +{ + struct rv_monitor *p = mon; + int retval = 0; + + list_for_each_entry_continue(p, &rv_monitors_list, list) { + if (retval || p->parent != mon) + break; + retval = rv_update_single(p, update, data); + } + if (retval) + rv_disable_container(mon); + update(mon, data); + return retval; +} + /** * rv_disable_monitor - disable a given runtime monitor * @mon: Pointer to the monitor definition structure. @@ -355,6 +384,26 @@ int rv_enable_monitor(struct rv_monitor *mon) return retval; } +/** + * rv_update_monitor - update and reenable a given runtime monitor + * @mon: Pointer to the monitor definition structure. + * @update: Pointer to the monitor update callback. + * @data: Context data passed to the update(). + * + * Returns 0 on success, error otherwise. + */ +int rv_update_monitor(struct rv_monitor *mon, rvmon_update_fn_t update, void *data) +{ + int retval; + + if (rv_is_container_monitor(mon)) + retval = rv_update_container(mon, update, data); + else + retval = rv_update_single(mon, update, data); + + return retval; +} + /* * interface for enabling/disabling a monitor. */ diff --git a/kernel/trace/rv/rv.h b/kernel/trace/rv/rv.h index 2c0f51ff9d5c..d0e89b8a66ac 100644 --- a/kernel/trace/rv/rv.h +++ b/kernel/trace/rv/rv.h @@ -26,8 +26,10 @@ extern struct mutex rv_interface_lock; extern struct list_head rv_monitors_list; struct dentry *get_monitors_root(void); +typedef void (rvmon_update_fn_t)(struct rv_monitor *mon, void *data); int rv_disable_monitor(struct rv_monitor *mon); int rv_enable_monitor(struct rv_monitor *mon); +int rv_update_monitor(struct rv_monitor *mon, rvmon_update_fn_t update, void *data); bool rv_is_container_monitor(struct rv_monitor *mon); bool rv_is_nested_monitor(struct rv_monitor *mon); diff --git a/kernel/trace/rv/rv_reactors.c b/kernel/trace/rv/rv_reactors.c index ea52f50e6453..06f21bcdd6cf 100644 --- a/kernel/trace/rv/rv_reactors.c +++ b/kernel/trace/rv/rv_reactors.c @@ -177,45 +177,25 @@ static const struct seq_operations monitor_reactors_seq_ops = { .show = monitor_reactor_show }; -static void monitor_swap_reactors_single(struct rv_monitor *mon, - struct rv_reactor *reactor, - bool nested) +static void monitor_update_reactor(struct rv_monitor *mon, void *data) { - bool monitor_enabled; + struct rv_reactor *reactor = data; - /* nothing to do */ - if (mon->reactor == reactor) + if (mon->reactor == data) return; - monitor_enabled = mon->enabled; - if (monitor_enabled) - rv_disable_monitor(mon); - mon->reactor = reactor; mon->react = reactor->react; - - /* enable only once if iterating through a container */ - if (monitor_enabled && !nested) - rv_enable_monitor(mon); } static void monitor_swap_reactors(struct rv_monitor *mon, struct rv_reactor *reactor) { - struct rv_monitor *p = mon; - - if (rv_is_container_monitor(mon)) - list_for_each_entry_continue(p, &rv_monitors_list, list) { - if (p->parent != mon) - break; - monitor_swap_reactors_single(p, reactor, true); - } /* - * This call enables and disables the monitor if they were active. - * In case of a container, we already disabled all and will enable all. - * All nested monitors are enabled also if they were off, we may refine - * this logic in the future. + * Update the reactor with the monitor quiesced: enabled monitors are + * disabled, updated and re-enabled, disabled ones are only updated. + * Children of a container keep their enabled state. */ - monitor_swap_reactors_single(mon, reactor, false); + rv_update_monitor(mon, monitor_update_reactor, reactor); } static ssize_t -- 2.55.0
