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


Reply via email to