@@ -162,7 +162,7 @@ struct dentry *get_monitors_root(void)
162162/*
163163 * Interface for the monitor register.
164164 */
165- static LIST_HEAD (rv_monitors_list );
165+ LIST_HEAD (rv_monitors_list );
166166
167167static int task_monitor_count ;
168168static bool task_monitor_slots [RV_PER_TASK_MONITORS ];
@@ -206,6 +206,30 @@ void rv_put_task_monitor_slot(int slot)
206206 task_monitor_slots [slot ] = false;
207207}
208208
209+ /*
210+ * Monitors with a parent are nested,
211+ * Monitors without a parent could be standalone or containers.
212+ */
213+ bool rv_is_nested_monitor (struct rv_monitor_def * mdef )
214+ {
215+ return mdef -> parent != NULL ;
216+ }
217+
218+ /*
219+ * We set our list to have nested monitors listed after their parent
220+ * if a monitor has a child element its a container.
221+ * Containers can be also identified based on their function pointers:
222+ * as they are not real monitors they do not need function definitions
223+ * for enable()/disable(). Use this condition to find empty containers.
224+ * Keep both conditions in case we have some non-compliant containers.
225+ */
226+ bool rv_is_container_monitor (struct rv_monitor_def * mdef )
227+ {
228+ struct rv_monitor_def * next = list_next_entry (mdef , list );
229+
230+ return next -> parent == mdef -> monitor || !mdef -> monitor -> enable ;
231+ }
232+
209233/*
210234 * This section collects the monitor/ files and folders.
211235 */
@@ -229,7 +253,8 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
229253
230254 if (mdef -> monitor -> enabled ) {
231255 mdef -> monitor -> enabled = 0 ;
232- mdef -> monitor -> disable ();
256+ if (mdef -> monitor -> disable )
257+ mdef -> monitor -> disable ();
233258
234259 /*
235260 * Wait for the execution of all events to finish.
@@ -243,6 +268,60 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
243268 return 0 ;
244269}
245270
271+ static void rv_disable_single (struct rv_monitor_def * mdef )
272+ {
273+ __rv_disable_monitor (mdef , true);
274+ }
275+
276+ static int rv_enable_single (struct rv_monitor_def * mdef )
277+ {
278+ int retval ;
279+
280+ lockdep_assert_held (& rv_interface_lock );
281+
282+ if (mdef -> monitor -> enabled )
283+ return 0 ;
284+
285+ retval = mdef -> monitor -> enable ();
286+
287+ if (!retval )
288+ mdef -> monitor -> enabled = 1 ;
289+
290+ return retval ;
291+ }
292+
293+ static void rv_disable_container (struct rv_monitor_def * mdef )
294+ {
295+ struct rv_monitor_def * p = mdef ;
296+ int enabled = 0 ;
297+
298+ list_for_each_entry_continue (p , & rv_monitors_list , list ) {
299+ if (p -> parent != mdef -> monitor )
300+ break ;
301+ enabled += __rv_disable_monitor (p , false);
302+ }
303+ if (enabled )
304+ tracepoint_synchronize_unregister ();
305+ mdef -> monitor -> enabled = 0 ;
306+ }
307+
308+ static int rv_enable_container (struct rv_monitor_def * mdef )
309+ {
310+ struct rv_monitor_def * p = mdef ;
311+ int retval = 0 ;
312+
313+ list_for_each_entry_continue (p , & rv_monitors_list , list ) {
314+ if (retval || p -> parent != mdef -> monitor )
315+ break ;
316+ retval = rv_enable_single (p );
317+ }
318+ if (retval )
319+ rv_disable_container (mdef );
320+ else
321+ mdef -> monitor -> enabled = 1 ;
322+ return retval ;
323+ }
324+
246325/**
247326 * rv_disable_monitor - disable a given runtime monitor
248327 * @mdef: Pointer to the monitor definition structure.
@@ -251,7 +330,11 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
251330 */
252331int rv_disable_monitor (struct rv_monitor_def * mdef )
253332{
254- __rv_disable_monitor (mdef , true);
333+ if (rv_is_container_monitor (mdef ))
334+ rv_disable_container (mdef );
335+ else
336+ rv_disable_single (mdef );
337+
255338 return 0 ;
256339}
257340
@@ -265,15 +348,10 @@ int rv_enable_monitor(struct rv_monitor_def *mdef)
265348{
266349 int retval ;
267350
268- lockdep_assert_held (& rv_interface_lock );
269-
270- if (mdef -> monitor -> enabled )
271- return 0 ;
272-
273- retval = mdef -> monitor -> enable ();
274-
275- if (!retval )
276- mdef -> monitor -> enabled = 1 ;
351+ if (rv_is_container_monitor (mdef ))
352+ retval = rv_enable_container (mdef );
353+ else
354+ retval = rv_enable_single (mdef );
277355
278356 return retval ;
279357}
@@ -336,9 +414,9 @@ static const struct file_operations interface_desc_fops = {
336414 * the monitor dir, where the specific options of the monitor
337415 * are exposed.
338416 */
339- static int create_monitor_dir (struct rv_monitor_def * mdef )
417+ static int create_monitor_dir (struct rv_monitor_def * mdef , struct rv_monitor_def * parent )
340418{
341- struct dentry * root = get_monitors_root ();
419+ struct dentry * root = parent ? parent -> root_d : get_monitors_root ();
342420 const char * name = mdef -> monitor -> name ;
343421 struct dentry * tmp ;
344422 int retval ;
@@ -377,7 +455,11 @@ static int monitors_show(struct seq_file *m, void *p)
377455{
378456 struct rv_monitor_def * mon_def = p ;
379457
380- seq_printf (m , "%s\n" , mon_def -> monitor -> name );
458+ if (mon_def -> parent )
459+ seq_printf (m , "%s:%s\n" , mon_def -> parent -> name ,
460+ mon_def -> monitor -> name );
461+ else
462+ seq_printf (m , "%s\n" , mon_def -> monitor -> name );
381463 return 0 ;
382464}
383465
@@ -514,7 +596,7 @@ static ssize_t enabled_monitors_write(struct file *filp, const char __user *user
514596 struct rv_monitor_def * mdef ;
515597 int retval = - EINVAL ;
516598 bool enable = true;
517- char * ptr ;
599+ char * ptr , * tmp ;
518600 int len ;
519601
520602 if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 1 )
@@ -541,6 +623,11 @@ static ssize_t enabled_monitors_write(struct file *filp, const char __user *user
541623
542624 retval = - EINVAL ;
543625
626+ /* we support 1 nesting level, trim the parent */
627+ tmp = strstr (ptr , ":" );
628+ if (tmp )
629+ ptr = tmp + 1 ;
630+
544631 list_for_each_entry (mdef , & rv_monitors_list , list ) {
545632 if (strcmp (ptr , mdef -> monitor -> name ) != 0 )
546633 continue ;
@@ -613,7 +700,7 @@ static void reset_all_monitors(void)
613700 struct rv_monitor_def * mdef ;
614701
615702 list_for_each_entry (mdef , & rv_monitors_list , list ) {
616- if (mdef -> monitor -> enabled )
703+ if (mdef -> monitor -> enabled && mdef -> monitor -> reset )
617704 mdef -> monitor -> reset ();
618705 }
619706}
@@ -685,45 +772,66 @@ static void destroy_monitor_dir(struct rv_monitor_def *mdef)
685772/**
686773 * rv_register_monitor - register a rv monitor.
687774 * @monitor: The rv_monitor to be registered.
775+ * @parent: The parent of the monitor to be registered, NULL if not nested.
688776 *
689777 * Returns 0 if successful, error otherwise.
690778 */
691- int rv_register_monitor (struct rv_monitor * monitor )
779+ int rv_register_monitor (struct rv_monitor * monitor , struct rv_monitor * parent )
692780{
693- struct rv_monitor_def * r ;
781+ struct rv_monitor_def * r , * p = NULL ;
694782 int retval = 0 ;
695783
696784 if (strlen (monitor -> name ) >= MAX_RV_MONITOR_NAME_SIZE ) {
697785 pr_info ("Monitor %s has a name longer than %d\n" , monitor -> name ,
698786 MAX_RV_MONITOR_NAME_SIZE );
699- return -1 ;
787+ return - EINVAL ;
700788 }
701789
702790 mutex_lock (& rv_interface_lock );
703791
704792 list_for_each_entry (r , & rv_monitors_list , list ) {
705793 if (strcmp (monitor -> name , r -> monitor -> name ) == 0 ) {
706794 pr_info ("Monitor %s is already registered\n" , monitor -> name );
707- retval = -1 ;
795+ retval = - EEXIST ;
708796 goto out_unlock ;
709797 }
710798 }
711799
800+ if (parent ) {
801+ list_for_each_entry (r , & rv_monitors_list , list ) {
802+ if (strcmp (parent -> name , r -> monitor -> name ) == 0 ) {
803+ p = r ;
804+ break ;
805+ }
806+ }
807+ }
808+
809+ if (p && rv_is_nested_monitor (p )) {
810+ pr_info ("Parent monitor %s is already nested, cannot nest further\n" ,
811+ parent -> name );
812+ return - EINVAL ;
813+ }
814+
712815 r = kzalloc (sizeof (struct rv_monitor_def ), GFP_KERNEL );
713816 if (!r ) {
714817 retval = - ENOMEM ;
715818 goto out_unlock ;
716819 }
717820
718821 r -> monitor = monitor ;
822+ r -> parent = parent ;
719823
720- retval = create_monitor_dir (r );
824+ retval = create_monitor_dir (r , p );
721825 if (retval ) {
722826 kfree (r );
723827 goto out_unlock ;
724828 }
725829
726- list_add_tail (& r -> list , & rv_monitors_list );
830+ /* keep children close to the parent for easier visualisation */
831+ if (p )
832+ list_add (& r -> list , & p -> list );
833+ else
834+ list_add_tail (& r -> list , & rv_monitors_list );
727835
728836out_unlock :
729837 mutex_unlock (& rv_interface_lock );
0 commit comments