delayacct: Add sysctl to enable at runtime
authorPeter Zijlstra <peterz@infradead.org>
Mon, 10 May 2021 12:01:00 +0000 (14:01 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Wed, 12 May 2021 09:43:25 +0000 (11:43 +0200)
Just like sched_schedstats, allow runtime enabling (and disabling) of
delayacct. This is useful if one forgot to add the delayacct boot time
option.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/YJkhebGJAywaZowX@hirez.programming.kicks-ass.net
Documentation/accounting/delay-accounting.rst
include/linux/delayacct.h
kernel/delayacct.c
kernel/sysctl.c

index f20b282..1b8b46d 100644 (file)
@@ -74,8 +74,10 @@ To enable, add::
 
    delayacct
 
-to the kernel boot options. The rest of the instructions
-below assume this has been done.
+to the kernel boot options. The rest of the instructions below assume this has
+been done. Alternatively, use sysctl kernel.task_delayacct to switch the state
+at runtime. Note however that only tasks started after enabling it will have
+delayacct information.
 
 After the system has booted up, use a utility
 similar to  getdelays.c to access the delays
index 225c8e0..af7e6eb 100644 (file)
@@ -65,6 +65,10 @@ DECLARE_STATIC_KEY_FALSE(delayacct_key);
 extern int delayacct_on;       /* Delay accounting turned on/off */
 extern struct kmem_cache *delayacct_cache;
 extern void delayacct_init(void);
+
+extern int sysctl_delayacct(struct ctl_table *table, int write, void *buffer,
+                           size_t *lenp, loff_t *ppos);
+
 extern void __delayacct_tsk_init(struct task_struct *);
 extern void __delayacct_tsk_exit(struct task_struct *);
 extern void __delayacct_blkio_start(void);
index 3f08690..51530d5 100644 (file)
@@ -18,6 +18,17 @@ DEFINE_STATIC_KEY_FALSE(delayacct_key);
 int delayacct_on __read_mostly;        /* Delay accounting turned on/off */
 struct kmem_cache *delayacct_cache;
 
+static void set_delayacct(bool enabled)
+{
+       if (enabled) {
+               static_branch_enable(&delayacct_key);
+               delayacct_on = 1;
+       } else {
+               delayacct_on = 0;
+               static_branch_disable(&delayacct_key);
+       }
+}
+
 static int __init delayacct_setup_enable(char *str)
 {
        delayacct_on = 1;
@@ -29,9 +40,30 @@ void delayacct_init(void)
 {
        delayacct_cache = KMEM_CACHE(task_delay_info, SLAB_PANIC|SLAB_ACCOUNT);
        delayacct_tsk_init(&init_task);
-       if (delayacct_on)
-               static_branch_enable(&delayacct_key);
+       set_delayacct(delayacct_on);
+}
+
+#ifdef CONFIG_PROC_SYSCTL
+int sysctl_delayacct(struct ctl_table *table, int write, void *buffer,
+                    size_t *lenp, loff_t *ppos)
+{
+       int state = delayacct_on;
+       struct ctl_table t;
+       int err;
+
+       if (write && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       t = *table;
+       t.data = &state;
+       err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
+       if (err < 0)
+               return err;
+       if (write)
+               set_delayacct(state);
+       return err;
 }
+#endif
 
 void __delayacct_tsk_init(struct task_struct *tsk)
 {
index 14edf84..0afbfc8 100644 (file)
@@ -71,6 +71,7 @@
 #include <linux/coredump.h>
 #include <linux/latencytop.h>
 #include <linux/pid.h>
+#include <linux/delayacct.h>
 
 #include "../lib/kstrtox.h"
 
@@ -1727,6 +1728,17 @@ static struct ctl_table kern_table[] = {
                .extra2         = SYSCTL_ONE,
        },
 #endif /* CONFIG_SCHEDSTATS */
+#ifdef CONFIG_TASK_DELAY_ACCT
+       {
+               .procname       = "task_delayacct",
+               .data           = NULL,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = sysctl_delayacct,
+               .extra1         = SYSCTL_ZERO,
+               .extra2         = SYSCTL_ONE,
+       },
+#endif /* CONFIG_TASK_DELAY_ACCT */
 #ifdef CONFIG_NUMA_BALANCING
        {
                .procname       = "numa_balancing",