From: Andrey Ryabinin <[email protected]>

Follow-up for 6d9a9210395e ("ve/page_alloc, kstat: account allocation latencies 
per-task")
Make per-thread and per-process allocation latencies:

  - /proc/<pid>/vz_latency - cumulative for a thread group
  - /proc/<pid>/tasks/<pid>/vz_latency - thread-specific

During allocation we collect per-thread latency. When thread dies,
it submits its own latencies into shared task->signal.alloc_lat struct.
/proc/<pid>/vz_latency - sums allocation latencies over all live threads
plus latencies of already dead tasks from task->signal.alloc_lat.

https://jira.sw.ru/browse/PSBM-81395
Signed-off-by: Andrey Ryabinin <[email protected]>
Reviewed-by: Kirill Tkhai <[email protected]>

Cc: Pavel Borzenkov <[email protected]>

Rebase to vz8:
 - As signal_struct moved from sched.h to sched/signal.h so changes did

(cherry-picked from c4cb66d5e70636c2089feb602226292a2513622a)
Signed-off-by: Andrey Zhadchenko <[email protected]>
---
 fs/proc/base.c               | 76 ++++++++++++++++++++++++++++++--------------
 include/linux/sched/signal.h |  3 ++
 kernel/exit.c                | 16 ++++++++++
 3 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index c8dc2e9..96db35f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -533,24 +533,23 @@ static void lastlat_seq_show(struct seq_file *m,
        seq_printf(m, "%-12s %20Lu %20lu\n", name,
                        snap->totlat, snap->count);
 }
+static const char *alloc_descr[] = {
+       "allocatomic:",
+       "alloc:",
+       "allocmp:",
+};
+static const int alloc_types[] = {
+       KSTAT_ALLOCSTAT_ATOMIC,
+       KSTAT_ALLOCSTAT_LOW,
+       KSTAT_ALLOCSTAT_LOW_MP,
+};
 
-static int vz_lat_show_proc(struct seq_file *m, void *v)
+static int proc_tid_vz_lat(struct seq_file *m, struct pid_namespace *ns,
+                       struct pid *pid, struct task_struct *task)
 {
        int i;
-       struct inode *inode = m->private;
-       struct task_struct *task = get_proc_task(inode);
-       static const char *alloc_descr[] = {
-               "allocatomic:",
-               "alloc:",
-               "allocmp:",
-       };
-       static const int alloc_types[] = {
-               KSTAT_ALLOCSTAT_ATOMIC,
-               KSTAT_ALLOCSTAT_LOW,
-               KSTAT_ALLOCSTAT_LOW_MP,
-       };
 
-       seq_printf(m, "%-11s %20s %20s\n",
+       seq_printf(m, "%-12s %20s %20s\n",
                        "Type", "Total_lat", "Calls");
 
        for (i = 0; i < ARRAY_SIZE(alloc_types); i++)
@@ -559,17 +558,43 @@ static int vz_lat_show_proc(struct seq_file *m, void *v)
        return 0;
 }
 
-static int vz_lat_open(struct inode *inode, struct file *file)
+static int proc_tgid_vz_lat(struct seq_file *m, struct pid_namespace *ns,
+                       struct pid *pid, struct task_struct *task)
 {
-       return single_open(file, vz_lat_show_proc, inode);
-}
+       int i;
+       unsigned long flags;
+       u64 lat[ARRAY_SIZE(alloc_types)];
+       u64 count[ARRAY_SIZE(alloc_types)];
 
-static const struct file_operations proc_vz_lat_operations = {
-       .open           = vz_lat_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+       for (i = 0; i < ARRAY_SIZE(alloc_types); i++) {
+               lat[i] = task->alloc_lat[alloc_types[i]].totlat;
+               count[i] = task->alloc_lat[alloc_types[i]].count;
+       }
+
+       if (lock_task_sighand(task, &flags)) {
+               struct task_struct *t = task;
+               while_each_thread(task, t) {
+                       for (i = 0; i < ARRAY_SIZE(alloc_types); i++) {
+                               lat[i] += t->alloc_lat[alloc_types[i]].totlat;
+                               count[i] += t->alloc_lat[alloc_types[i]].count;
+                       }
+               }
+               for (i = 0; i < ARRAY_SIZE(alloc_types); i++) {
+                       lat[i] += t->signal->alloc_lat[alloc_types[i]].totlat;
+                       count[i] += t->signal->alloc_lat[alloc_types[i]].count;
+               }
+               unlock_task_sighand(task, &flags);
+       }
+
+       seq_printf(m, "%-12s %20s %20s\n",
+                       "Type", "Total_lat", "Calls");
+
+       for (i = 0; i < ARRAY_SIZE(alloc_types); i++)
+               seq_printf(m, "%-12s %20Lu %20Lu\n", alloc_descr[i],
+                       lat[i], count[i]);
+
+       return 0;
+}
 #endif
 
 static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns,
@@ -3097,7 +3122,7 @@ static int proc_pid_patch_state(struct seq_file *m, 
struct pid_namespace *ns,
        ONE("patch_state",  S_IRUSR, proc_pid_patch_state),
 #endif
 #ifdef CONFIG_VE
-       REG("vz_latency", S_IRUGO, proc_vz_lat_operations),
+       ONE("vz_latency", S_IRUGO, proc_tgid_vz_lat),
 #endif
 };
 
@@ -3480,6 +3505,9 @@ static int proc_tid_comm_permission(struct inode *inode, 
int mask)
 #ifdef CONFIG_LIVEPATCH
        ONE("patch_state",  S_IRUSR, proc_pid_patch_state),
 #endif
+#ifdef CONFIG_VE
+       ONE("vz_latency", S_IRUGO, proc_tid_vz_lat),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 57cf2c5..adfe9cc 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -211,6 +211,9 @@ struct signal_struct {
 #ifdef CONFIG_TASKSTATS
        struct taskstats *stats;
 #endif
+#ifdef CONFIG_VE
+       struct kstat_lat_snap_struct alloc_lat[KSTAT_ALLOCSTAT_NR];
+#endif
 #ifdef CONFIG_AUDIT
        unsigned audit_tty;
        struct tty_audit_buf *tty_audit_buf;
diff --git a/kernel/exit.c b/kernel/exit.c
index 0922ca9..8fde663 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -723,6 +723,20 @@ static void check_stack_usage(void)
 static inline void check_stack_usage(void) {}
 #endif
 
+void kstat_add_dying(struct task_struct *tsk)
+{
+#ifdef CONFIG_VE
+       int i;
+
+       spin_lock_irq(&tsk->sighand->siglock);
+       for (i = 0; i < KSTAT_ALLOCSTAT_NR; i++) {
+               tsk->signal->alloc_lat[i].totlat += tsk->alloc_lat[i].totlat;
+               tsk->signal->alloc_lat[i].count += tsk->alloc_lat[i].count;
+       }
+       spin_unlock_irq(&tsk->sighand->siglock);
+#endif
+}
+
 void __noreturn do_exit(long code)
 {
        struct task_struct *tsk = current;
@@ -791,6 +805,8 @@ void __noreturn do_exit(long code)
 #endif
                if (tsk->mm)
                        setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm);
+       } else {
+               kstat_add_dying(tsk);
        }
        acct_collect(code, group_dead);
        if (group_dead)
-- 
1.8.3.1

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to