@@ -162,7 +162,7 @@ struct dentry *get_monitors_root(void)
162
162
/*
163
163
* Interface for the monitor register.
164
164
*/
165
- static LIST_HEAD (rv_monitors_list );
165
+ LIST_HEAD (rv_monitors_list );
166
166
167
167
static int task_monitor_count ;
168
168
static bool task_monitor_slots [RV_PER_TASK_MONITORS ];
@@ -206,6 +206,30 @@ void rv_put_task_monitor_slot(int slot)
206
206
task_monitor_slots [slot ] = false;
207
207
}
208
208
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
+
209
233
/*
210
234
* This section collects the monitor/ files and folders.
211
235
*/
@@ -229,7 +253,8 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
229
253
230
254
if (mdef -> monitor -> enabled ) {
231
255
mdef -> monitor -> enabled = 0 ;
232
- mdef -> monitor -> disable ();
256
+ if (mdef -> monitor -> disable )
257
+ mdef -> monitor -> disable ();
233
258
234
259
/*
235
260
* 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)
243
268
return 0 ;
244
269
}
245
270
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
+
246
325
/**
247
326
* rv_disable_monitor - disable a given runtime monitor
248
327
* @mdef: Pointer to the monitor definition structure.
@@ -251,7 +330,11 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
251
330
*/
252
331
int rv_disable_monitor (struct rv_monitor_def * mdef )
253
332
{
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
+
255
338
return 0 ;
256
339
}
257
340
@@ -265,15 +348,10 @@ int rv_enable_monitor(struct rv_monitor_def *mdef)
265
348
{
266
349
int retval ;
267
350
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 );
277
355
278
356
return retval ;
279
357
}
@@ -336,9 +414,9 @@ static const struct file_operations interface_desc_fops = {
336
414
* the monitor dir, where the specific options of the monitor
337
415
* are exposed.
338
416
*/
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 )
340
418
{
341
- struct dentry * root = get_monitors_root ();
419
+ struct dentry * root = parent ? parent -> root_d : get_monitors_root ();
342
420
const char * name = mdef -> monitor -> name ;
343
421
struct dentry * tmp ;
344
422
int retval ;
@@ -377,7 +455,11 @@ static int monitors_show(struct seq_file *m, void *p)
377
455
{
378
456
struct rv_monitor_def * mon_def = p ;
379
457
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 );
381
463
return 0 ;
382
464
}
383
465
@@ -514,7 +596,7 @@ static ssize_t enabled_monitors_write(struct file *filp, const char __user *user
514
596
struct rv_monitor_def * mdef ;
515
597
int retval = - EINVAL ;
516
598
bool enable = true;
517
- char * ptr ;
599
+ char * ptr , * tmp ;
518
600
int len ;
519
601
520
602
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
541
623
542
624
retval = - EINVAL ;
543
625
626
+ /* we support 1 nesting level, trim the parent */
627
+ tmp = strstr (ptr , ":" );
628
+ if (tmp )
629
+ ptr = tmp + 1 ;
630
+
544
631
list_for_each_entry (mdef , & rv_monitors_list , list ) {
545
632
if (strcmp (ptr , mdef -> monitor -> name ) != 0 )
546
633
continue ;
@@ -613,7 +700,7 @@ static void reset_all_monitors(void)
613
700
struct rv_monitor_def * mdef ;
614
701
615
702
list_for_each_entry (mdef , & rv_monitors_list , list ) {
616
- if (mdef -> monitor -> enabled )
703
+ if (mdef -> monitor -> enabled && mdef -> monitor -> reset )
617
704
mdef -> monitor -> reset ();
618
705
}
619
706
}
@@ -685,45 +772,66 @@ static void destroy_monitor_dir(struct rv_monitor_def *mdef)
685
772
/**
686
773
* rv_register_monitor - register a rv monitor.
687
774
* @monitor: The rv_monitor to be registered.
775
+ * @parent: The parent of the monitor to be registered, NULL if not nested.
688
776
*
689
777
* Returns 0 if successful, error otherwise.
690
778
*/
691
- int rv_register_monitor (struct rv_monitor * monitor )
779
+ int rv_register_monitor (struct rv_monitor * monitor , struct rv_monitor * parent )
692
780
{
693
- struct rv_monitor_def * r ;
781
+ struct rv_monitor_def * r , * p = NULL ;
694
782
int retval = 0 ;
695
783
696
784
if (strlen (monitor -> name ) >= MAX_RV_MONITOR_NAME_SIZE ) {
697
785
pr_info ("Monitor %s has a name longer than %d\n" , monitor -> name ,
698
786
MAX_RV_MONITOR_NAME_SIZE );
699
- return -1 ;
787
+ return - EINVAL ;
700
788
}
701
789
702
790
mutex_lock (& rv_interface_lock );
703
791
704
792
list_for_each_entry (r , & rv_monitors_list , list ) {
705
793
if (strcmp (monitor -> name , r -> monitor -> name ) == 0 ) {
706
794
pr_info ("Monitor %s is already registered\n" , monitor -> name );
707
- retval = -1 ;
795
+ retval = - EEXIST ;
708
796
goto out_unlock ;
709
797
}
710
798
}
711
799
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
+
712
815
r = kzalloc (sizeof (struct rv_monitor_def ), GFP_KERNEL );
713
816
if (!r ) {
714
817
retval = - ENOMEM ;
715
818
goto out_unlock ;
716
819
}
717
820
718
821
r -> monitor = monitor ;
822
+ r -> parent = parent ;
719
823
720
- retval = create_monitor_dir (r );
824
+ retval = create_monitor_dir (r , p );
721
825
if (retval ) {
722
826
kfree (r );
723
827
goto out_unlock ;
724
828
}
725
829
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 );
727
835
728
836
out_unlock :
729
837
mutex_unlock (& rv_interface_lock );
0 commit comments