Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755144AbcDKXhc (ORCPT ); Mon, 11 Apr 2016 19:37:32 -0400 Received: from mail-pa0-f50.google.com ([209.85.220.50]:33507 "EHLO mail-pa0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755479AbcDKXg0 (ORCPT ); Mon, 11 Apr 2016 19:36:26 -0400 From: Andrey Vagin To: linux-kernel@vger.kernel.org Cc: Andrey Vagin , Oleg Nesterov , Andrew Morton , Cyrill Gorcunov , Pavel Emelyanov , Roger Luethi , Arnd Bergmann , Arnaldo Carvalho de Melo , David Ahern , Andy Lutomirski , Pavel Odintsov Subject: [PATCH 10/15] task_diag: add a new group to get resource usage Date: Mon, 11 Apr 2016 16:35:50 -0700 Message-Id: <1460417755-18201-11-git-send-email-avagin@openvz.org> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1460417755-18201-1-git-send-email-avagin@openvz.org> References: <1460417755-18201-1-git-send-email-avagin@openvz.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4050 Lines: 158 Signed-off-by: Andrey Vagin --- fs/proc/task_diag.c | 92 ++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/task_diag.h | 15 +++++++ 2 files changed, 107 insertions(+) diff --git a/fs/proc/task_diag.c b/fs/proc/task_diag.c index cd10374..c8499f2 100644 --- a/fs/proc/task_diag.c +++ b/fs/proc/task_diag.c @@ -390,6 +390,84 @@ err: return rc; } +static int fill_task_stat(struct task_struct *task, struct sk_buff *skb, int whole) +{ + struct task_diag_stat *st; + struct nlattr *attr; + + int priority, nice; + int num_threads = 0; + unsigned long cmin_flt = 0, cmaj_flt = 0; + unsigned long min_flt = 0, maj_flt = 0; + cputime_t cutime, cstime, utime, stime; + cputime_t cgtime, gtime; + unsigned long flags; + + attr = nla_reserve(skb, TASK_DIAG_STAT, sizeof(struct task_diag_stat)); + if (!attr) + return -EMSGSIZE; + + st = nla_data(attr); + + cutime = cstime = utime = stime = 0; + cgtime = gtime = 0; + if (lock_task_sighand(task, &flags)) { + struct signal_struct *sig = task->signal; + + num_threads = get_nr_threads(task); + + cmin_flt = sig->cmin_flt; + cmaj_flt = sig->cmaj_flt; + cutime = sig->cutime; + cstime = sig->cstime; + cgtime = sig->cgtime; + + /* add up live thread stats at the group level */ + if (whole) { + struct task_struct *t = task; + + do { + min_flt += t->min_flt; + maj_flt += t->maj_flt; + gtime += task_gtime(t); + } while_each_thread(task, t); + + min_flt += sig->min_flt; + maj_flt += sig->maj_flt; + thread_group_cputime_adjusted(task, &utime, &stime); + gtime += sig->gtime; + } + + unlock_task_sighand(task, &flags); + } + + if (!whole) { + min_flt = task->min_flt; + maj_flt = task->maj_flt; + task_cputime_adjusted(task, &utime, &stime); + gtime = task_gtime(task); + } + + /* scale priority and nice values from timeslices to -20..20 */ + /* to make it look like a "normal" Unix priority/nice value */ + priority = task_prio(task); + nice = task_nice(task); + + + st->minflt = min_flt; + st->cminflt = cmin_flt; + st->majflt = maj_flt; + st->cmajflt = cmaj_flt; + st->utime = cputime_to_clock_t(utime); + st->stime = cputime_to_clock_t(stime); + st->cutime = cputime_to_clock_t(cutime); + st->cstime = cputime_to_clock_t(cstime); + + st->threads = num_threads; + + return 0; +} + static int task_diag_fill(struct task_struct *tsk, struct sk_buff *skb, struct task_diag_pid *req, struct task_diag_cb *cb, struct pid_namespace *pidns, @@ -451,6 +529,20 @@ static int task_diag_fill(struct task_struct *tsk, struct sk_buff *skb, i++; } + if (show_flags & TASK_DIAG_SHOW_STAT) { + int whole = 1; + + if (req->dump_strategy == TASK_DIAG_DUMP_ALL_THREAD || + req->dump_strategy == TASK_DIAG_DUMP_THREAD) + whole = 0; + + if (i >= n) + err = fill_task_stat(tsk, skb, whole); + if (err) + goto err; + i++; + } + msg->flags &= ~TASK_DIAG_FLAG_CONT; nlmsg_end(skb, nlh); diff --git a/include/uapi/linux/task_diag.h b/include/uapi/linux/task_diag.h index e967c5b..551d4fa 100644 --- a/include/uapi/linux/task_diag.h +++ b/include/uapi/linux/task_diag.h @@ -20,6 +20,7 @@ enum { TASK_DIAG_CRED, TASK_DIAG_VMA, TASK_DIAG_VMA_STAT, + TASK_DIAG_STAT, __TASK_DIAG_ATTR_MAX #define TASK_DIAG_ATTR_MAX (__TASK_DIAG_ATTR_MAX - 1) @@ -29,6 +30,7 @@ enum { #define TASK_DIAG_SHOW_CRED (1ULL << TASK_DIAG_CRED) #define TASK_DIAG_SHOW_VMA (1ULL << TASK_DIAG_VMA) #define TASK_DIAG_SHOW_VMA_STAT (1ULL << TASK_DIAG_VMA_STAT) +#define TASK_DIAG_SHOW_STAT (1ULL << TASK_DIAG_STAT) enum { TASK_DIAG_RUNNING, @@ -153,6 +155,19 @@ struct task_diag_vma_stat *task_diag_vma_stat(struct task_diag_vma *vma) (void *) vma < nla_data(attr) + nla_len(attr); \ vma = (void *) vma + vma->vma_len) +struct task_diag_stat { + __u64 minflt; + __u64 cminflt; + __u64 majflt; + __u64 cmajflt; + __u64 utime; + __u64 stime; + __u64 cutime; + __u64 cstime; + + __u32 threads; +}; + #define TASK_DIAG_DUMP_ALL 0 #define TASK_DIAG_DUMP_ONE 1 #define TASK_DIAG_DUMP_ALL_THREAD 2 -- 2.5.5