Release 4.15 kernel/taskstats.c
/*
* taskstats.c - Export per-task statistics to userland
*
* Copyright (C) Shailabh Nagar, IBM Corp. 2006
* (C) Balbir Singh, IBM Corp. 2006
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/taskstats_kern.h>
#include <linux/tsacct_kern.h>
#include <linux/delayacct.h>
#include <linux/cpumask.h>
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/cgroupstats.h>
#include <linux/cgroup.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/pid_namespace.h>
#include <net/genetlink.h>
#include <linux/atomic.h>
#include <linux/sched/cputime.h>
/*
* Maximum length of a cpumask that can be specified in
* the TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK attribute
*/
#define TASKSTATS_CPUMASK_MAXLEN (100+6*NR_CPUS)
static DEFINE_PER_CPU(__u32, taskstats_seqnum);
static int family_registered;
struct kmem_cache *taskstats_cache;
static struct genl_family family;
static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
[TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 },
[TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 },
[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};
/*
* We have to use TASKSTATS_CMD_ATTR_MAX here, it is the maxattr in the family.
* Make sure they are always aligned.
*/
static const struct nla_policy cgroupstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
[CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 },
};
struct listener {
struct list_head list;
pid_t pid;
char valid;
};
struct listener_list {
struct rw_semaphore sem;
struct list_head list;
};
static DEFINE_PER_CPU(struct listener_list, listener_array);
enum actions {
REGISTER,
DEREGISTER,
CPU_DONT_CARE
};
static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
size_t size)
{
struct sk_buff *skb;
void *reply;
/*
* If new attributes are added, please revisit this allocation
*/
skb = genlmsg_new(size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
if (!info) {
int seq = this_cpu_inc_return(taskstats_seqnum) - 1;
reply = genlmsg_put(skb, 0, seq, &family, 0, cmd);
} else
reply = genlmsg_put_reply(skb, info, &family, 0, cmd);
if (reply == NULL) {
nlmsg_free(skb);
return -EINVAL;
}
*skbp = skb;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 117 | 91.41% | 1 | 14.29% |
Thomas Graf | 7 | 5.47% | 4 | 57.14% |
Christoph Lameter | 3 | 2.34% | 1 | 14.29% |
Balbir Singh | 1 | 0.78% | 1 | 14.29% |
Total | 128 | 100.00% | 7 | 100.00% |
/*
* Send taskstats data in @skb to listener with nl_pid @pid
*/
static int send_reply(struct sk_buff *skb, struct genl_info *info)
{
struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
void *reply = genlmsg_data(genlhdr);
genlmsg_end(skb, reply);
return genlmsg_reply(skb, info);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 44 | 83.02% | 2 | 50.00% |
Johannes Berg | 6 | 11.32% | 1 | 25.00% |
Arnaldo Carvalho de Melo | 3 | 5.66% | 1 | 25.00% |
Total | 53 | 100.00% | 4 | 100.00% |
/*
* Send taskstats data in @skb to listeners registered for @cpu's exit data
*/
static void send_cpu_listeners(struct sk_buff *skb,
struct listener_list *listeners)
{
struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
struct listener *s, *tmp;
struct sk_buff *skb_next, *skb_cur = skb;
void *reply = genlmsg_data(genlhdr);
int rc, delcount = 0;
genlmsg_end(skb, reply);
rc = 0;
down_read(&listeners->sem);
list_for_each_entry(s, &listeners->list, list) {
skb_next = NULL;
if (!list_is_last(&s->list, &listeners->list)) {
skb_next = skb_clone(skb_cur, GFP_KERNEL);
if (!skb_next)
break;
}
rc = genlmsg_unicast(&init_net, skb_cur, s->pid);
if (rc == -ECONNREFUSED) {
s->valid = 0;
delcount++;
}
skb_cur = skb_next;
}
up_read(&listeners->sem);
if (skb_cur)
nlmsg_free(skb_cur);
if (!delcount)
return;
/* Delete invalidated entries */
down_write(&listeners->sem);
list_for_each_entry_safe(s, tmp, &listeners->list, list) {
if (!s->valid) {
list_del(&s->list);
kfree(s);
}
}
up_write(&listeners->sem);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 229 | 95.82% | 4 | 57.14% |
Oleg Nesterov | 4 | 1.67% | 1 | 14.29% |
Arnaldo Carvalho de Melo | 3 | 1.26% | 1 | 14.29% |
Johannes Berg | 3 | 1.26% | 1 | 14.29% |
Total | 239 | 100.00% | 7 | 100.00% |
static void fill_stats(struct user_namespace *user_ns,
struct pid_namespace *pid_ns,
struct task_struct *tsk, struct taskstats *stats)
{
memset(stats, 0, sizeof(*stats));
/*
* Each accounting subsystem adds calls to its functions to
* fill in relevant parts of struct taskstsats as follows
*
* per-task-foo(stats, tsk);
*/
delayacct_add_tsk(stats, tsk);
/* fill in basic acct fields */
stats->version = TASKSTATS_VERSION;
stats->nvcsw = tsk->nvcsw;
stats->nivcsw = tsk->nivcsw;
bacct_add_tsk(user_ns, pid_ns, stats, tsk);
/* fill in extended acct fields */
xacct_add_tsk(stats, tsk);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 26 | 29.21% | 3 | 30.00% |
Jay Lan | 16 | 17.98% | 2 | 20.00% |
Maxim Uvarov | 16 | 17.98% | 1 | 10.00% |
Oleg Nesterov | 14 | 15.73% | 2 | 20.00% |
Eric W. Biedermann | 14 | 15.73% | 1 | 10.00% |
Michael Holzheu | 3 | 3.37% | 1 | 10.00% |
Total | 89 | 100.00% | 10 | 100.00% |
static int fill_stats_for_pid(pid_t pid, struct taskstats *stats)
{
struct task_struct *tsk;
rcu_read_lock();
tsk = find_task_by_vpid(pid);
if (tsk)
get_task_struct(tsk);
rcu_read_unlock();
if (!tsk)
return -ESRCH;
fill_stats(current_user_ns(), task_active_pid_ns(current), tsk, stats);
put_task_struct(tsk);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michael Holzheu | 57 | 78.08% | 1 | 33.33% |
Shailabh Nagar | 8 | 10.96% | 1 | 33.33% |
Eric W. Biedermann | 8 | 10.96% | 1 | 33.33% |
Total | 73 | 100.00% | 3 | 100.00% |
static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
{
struct task_struct *tsk, *first;
unsigned long flags;
int rc = -ESRCH;
u64 delta, utime, stime;
u64 start_time;
/*
* Add additional stats from live tasks except zombie thread group
* leaders who are already counted with the dead tasks
*/
rcu_read_lock();
first = find_task_by_vpid(tgid);
if (!first || !lock_task_sighand(first, &flags))
goto out;
if (first->signal->stats)
memcpy(stats, first->signal->stats, sizeof(*stats));
else
memset(stats, 0, sizeof(*stats));
tsk = first;
start_time = ktime_get_ns();
do {
if (tsk->exit_state)
continue;
/*
* Accounting subsystem can call its functions here to
* fill in relevant parts of struct taskstsats as follows
*
* per-task-foo(stats, tsk);
*/
delayacct_add_tsk(stats, tsk);
/* calculate task elapsed time in nsec */
delta = start_time - tsk->start_time;
/* Convert to micro seconds */
do_div(delta, NSEC_PER_USEC);
stats->ac_etime += delta;
task_cputime(tsk, &utime, &stime);
stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
stats->nvcsw += tsk->nvcsw;
stats->nivcsw += tsk->nivcsw;
} while_each_thread(first, tsk);
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 88 | 41.51% | 3 | 33.33% |
Zhang Xiao | 71 | 33.49% | 1 | 11.11% |
Oleg Nesterov | 32 | 15.09% | 2 | 22.22% |
Maxim Uvarov | 16 | 7.55% | 1 | 11.11% |
Michael Holzheu | 4 | 1.89% | 1 | 11.11% |
Pavel Emelyanov | 1 | 0.47% | 1 | 11.11% |
Total | 212 | 100.00% | 9 | 100.00% |
unlock_task_sighand(first, &flags);
rc = 0;
out:
rcu_read_unlock();
stats->version = TASKSTATS_VERSION;
/*
* Accounting subsystems can also add calls here to modify
* fields of taskstats.
*/
return rc;
}
static
void fill_tgid_exit(struct task_struct *tsk)
{
unsigned long flags;
spin_lock_irqsave(&tsk->sighand->siglock, flags);
if (!tsk->signal->stats)
goto ret;
/*
* Each accounting subsystem calls its functions here to
* accumalate its per-task stats for tsk, into the per-tgid structure
*
* per-task-foo(tsk->signal->stats, tsk);
*/
delayacct_add_tsk(tsk->signal->stats, tsk);
ret:
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
return;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 61 | 92.42% | 2 | 50.00% |
Oleg Nesterov | 4 | 6.06% | 1 | 25.00% |
Michael Holzheu | 1 | 1.52% | 1 | 25.00% |
Total | 66 | 100.00% | 4 | 100.00% |
static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
{
struct listener_list *listeners;
struct listener *s, *tmp, *s2;
unsigned int cpu;
int ret = 0;
if (!cpumask_subset(mask, cpu_possible_mask))
return -EINVAL;
if (current_user_ns() != &init_user_ns)
return -EINVAL;
if (task_active_pid_ns(current) != &init_pid_ns)
return -EINVAL;
if (isadd == REGISTER) {
for_each_cpu(cpu, mask) {
s = kmalloc_node(sizeof(struct listener),
GFP_KERNEL, cpu_to_node(cpu));
if (!s) {
ret = -ENOMEM;
goto cleanup;
}
s->pid = pid;
s->valid = 1;
listeners = &per_cpu(listener_array, cpu);
down_write(&listeners->sem);
list_for_each_entry(s2, &listeners->list, list) {
if (s2->pid == pid && s2->valid)
goto exists;
}
list_add(&s->list, &listeners->list);
s = NULL;
exists:
up_write(&listeners->sem);
kfree(s); /* nop if NULL */
}
return 0;
}
/* Deregister or cleanup */
cleanup:
for_each_cpu(cpu, mask) {
listeners = &per_cpu(listener_array, cpu);
down_write(&listeners->sem);
list_for_each_entry_safe(s, tmp, &listeners->list, list) {
if (s->pid == pid) {
list_del(&s->list);
kfree(s);
break;
}
}
up_write(&listeners->sem);
}
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 211 | 70.57% | 2 | 25.00% |
Vasiliy Kulikov | 32 | 10.70% | 1 | 12.50% |
Eric W. Biedermann | 26 | 8.70% | 1 | 12.50% |
Chen Gang S | 13 | 4.35% | 1 | 12.50% |
Oleg Nesterov | 9 | 3.01% | 2 | 25.00% |
Rusty Russell | 8 | 2.68% | 1 | 12.50% |
Total | 299 | 100.00% | 8 | 100.00% |
static int parse(struct nlattr *na, struct cpumask *mask)
{
char *data;
int len;
int ret;
if (na == NULL)
return 1;
len = nla_len(na);
if (len > TASKSTATS_CPUMASK_MAXLEN)
return -E2BIG;
if (len < 1)
return -EINVAL;
data = kmalloc(len, GFP_KERNEL);
if (!data)
return -ENOMEM;
nla_strlcpy(data, na, len);
ret = cpulist_parse(data, mask);
kfree(data);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 104 | 98.11% | 2 | 66.67% |
Rusty Russell | 2 | 1.89% | 1 | 33.33% |
Total | 106 | 100.00% | 3 | 100.00% |
static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)
{
struct nlattr *na, *ret;
int aggr;
aggr = (type == TASKSTATS_TYPE_PID)
? TASKSTATS_TYPE_AGGR_PID
: TASKSTATS_TYPE_AGGR_TGID;
na = nla_nest_start(skb, aggr);
if (!na)
goto err;
if (nla_put(skb, type, sizeof(pid), &pid) < 0) {
nla_nest_cancel(skb, na);
goto err;
}
ret = nla_reserve_64bit(skb, TASKSTATS_TYPE_STATS,
sizeof(struct taskstats), TASKSTATS_TYPE_NULL);
if (!ret) {
nla_nest_cancel(skb, na);
goto err;
}
nla_nest_end(skb, na);
return nla_data(ret);
err:
return NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Oleg Nesterov | 115 | 80.99% | 3 | 50.00% |
Chen Gang S | 18 | 12.68% | 1 | 16.67% |
Jeff Mahoney | 6 | 4.23% | 1 | 16.67% |
Nicolas Dichtel | 3 | 2.11% | 1 | 16.67% |
Total | 142 | 100.00% | 6 | 100.00% |
static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
{
int rc = 0;
struct sk_buff *rep_skb;
struct cgroupstats *stats;
struct nlattr *na;
size_t size;
u32 fd;
struct fd f;
na = info->attrs[CGROUPSTATS_CMD_ATTR_FD];
if (!na)
return -EINVAL;
fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
f = fdget(fd);
if (!f.file)
return 0;
size = nla_total_size(sizeof(struct cgroupstats));
rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
size);
if (rc < 0)
goto err;
na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
sizeof(struct cgroupstats));
if (na == NULL) {
nlmsg_free(rep_skb);
rc = -EMSGSIZE;
goto err;
}
stats = nla_data(na);
memset(stats, 0, sizeof(*stats));
rc = cgroupstats_build(stats, f.file->f_path.dentry);
if (rc < 0) {
nlmsg_free(rep_skb);
goto err;
}
rc = send_reply(rep_skb, info);
err:
fdput(f);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Balbir Singh | 185 | 79.40% | 1 | 16.67% |
Alan Cox | 16 | 6.87% | 1 | 16.67% |
Adrian Bunk | 14 | 6.01% | 1 | 16.67% |
Al Viro | 13 | 5.58% | 2 | 33.33% |
Jesper Juhl | 5 | 2.15% | 1 | 16.67% |
Total | 233 | 100.00% | 6 | 100.00% |
static int cmd_attr_register_cpumask(struct genl_info *info)
{
cpumask_var_t mask;
int rc;
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], mask);
if (rc < 0)
goto out;
rc = add_del_listener(info->snd_portid, mask, REGISTER);
out:
free_cpumask_var(mask);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 40 | 51.28% | 3 | 50.00% |
Rusty Russell | 22 | 28.21% | 1 | 16.67% |
Michael Holzheu | 15 | 19.23% | 1 | 16.67% |
Eric W. Biedermann | 1 | 1.28% | 1 | 16.67% |
Total | 78 | 100.00% | 6 | 100.00% |
static int cmd_attr_deregister_cpumask(struct genl_info *info)
{
cpumask_var_t mask;
int rc;
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], mask);
if (rc < 0)
goto out;
rc = add_del_listener(info->snd_portid, mask, DEREGISTER);
out:
free_cpumask_var(mask);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michael Holzheu | 33 | 42.31% | 1 | 25.00% |
Shailabh Nagar | 30 | 38.46% | 1 | 25.00% |
Rusty Russell | 14 | 17.95% | 1 | 25.00% |
Eric W. Biedermann | 1 | 1.28% | 1 | 25.00% |
Total | 78 | 100.00% | 4 | 100.00% |
static size_t taskstats_packet_size(void)
{
size_t size;
size = nla_total_size(sizeof(u32)) +
nla_total_size_64bit(sizeof(struct taskstats)) +
nla_total_size(0);
return size;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jeff Mahoney | 37 | 97.37% | 1 | 50.00% |
Nicolas Dichtel | 1 | 2.63% | 1 | 50.00% |
Total | 38 | 100.00% | 2 | 100.00% |
static int cmd_attr_pid(struct genl_info *info)
{
struct taskstats *stats;
struct sk_buff *rep_skb;
size_t size;
u32 pid;
int rc;
size = taskstats_packet_size();
rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
if (rc < 0)
return rc;
rc = -EINVAL;
pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]);
stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid);
if (!stats)
goto err;
rc = fill_stats_for_pid(pid, stats);
if (rc < 0)
goto err;
return send_reply(rep_skb, info);
err:
nlmsg_free(rep_skb);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 53 | 40.77% | 1 | 14.29% |
Michael Holzheu | 50 | 38.46% | 2 | 28.57% |
Oleg Nesterov | 25 | 19.23% | 3 | 42.86% |
Jeff Mahoney | 2 | 1.54% | 1 | 14.29% |
Total | 130 | 100.00% | 7 | 100.00% |
static int cmd_attr_tgid(struct genl_info *info)
{
struct taskstats *stats;
struct sk_buff *rep_skb;
size_t size;
u32 tgid;
int rc;
size = taskstats_packet_size();
rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
if (rc < 0)
return rc;
rc = -EINVAL;
tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]);
stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid);
if (!stats)
goto err;
rc = fill_stats_for_tgid(tgid, stats);
if (rc < 0)
goto err;
return send_reply(rep_skb, info);
err:
nlmsg_free(rep_skb);
return rc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michael Holzheu | 60 | 46.15% | 2 | 28.57% |
Shailabh Nagar | 48 | 36.92% | 1 | 14.29% |
Oleg Nesterov | 20 | 15.38% | 3 | 42.86% |
Jeff Mahoney | 2 | 1.54% | 1 | 14.29% |
Total | 130 | 100.00% | 7 | 100.00% |
static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
{
if (info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK])
return cmd_attr_register_cpumask(info);
else if (info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK])
return cmd_attr_deregister_cpumask(info);
else if (info->attrs[TASKSTATS_CMD_ATTR_PID])
return cmd_attr_pid(info);
else if (info->attrs[TASKSTATS_CMD_ATTR_TGID])
return cmd_attr_tgid(info);
else
return -EINVAL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Michael Holzheu | 84 | 100.00% | 1 | 100.00% |
Total | 84 | 100.00% | 1 | 100.00% |
static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk)
{
struct signal_struct *sig = tsk->signal;
struct taskstats *stats;
if (sig->stats || thread_group_empty(tsk))
goto ret;
/* No problem if kmem_cache_zalloc() fails */
stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
spin_lock_irq(&tsk->sighand->siglock);
if (!sig->stats) {
sig->stats = stats;
stats = NULL;
}
spin_unlock_irq(&tsk->sighand->siglock);
if (stats)
kmem_cache_free(taskstats_cache, stats);
ret:
return sig->stats;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Oleg Nesterov | 108 | 100.00% | 1 | 100.00% |
Total | 108 | 100.00% | 1 | 100.00% |
/* Send pid data out on exit */
void taskstats_exit(struct task_struct *tsk, int group_dead)
{
int rc;
struct listener_list *listeners;
struct taskstats *stats;
struct sk_buff *rep_skb;
size_t size;
int is_thread_group;
if (!family_registered)
return;
/*
* Size includes space for nested attributes
*/
size = taskstats_packet_size();
is_thread_group = !!taskstats_tgid_alloc(tsk);
if (is_thread_group) {
/* PID + STATS + TGID + STATS */
size = 2 * size;
/* fill the tsk->signal->stats structure */
fill_tgid_exit(tsk);
}
listeners = raw_cpu_ptr(&listener_array);
if (list_empty(&listeners->list))
return;
rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, size);
if (rc < 0)
return;
stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID,
task_pid_nr_ns(tsk, &init_pid_ns));
if (!stats)
goto err;
fill_stats(&init_user_ns, &init_pid_ns, tsk, stats);
/*
* Doesn't matter if tsk is the leader or the last group member leaving
*/
if (!is_thread_group || !group_dead)
goto send;
stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID,
task_tgid_nr_ns(tsk, &init_pid_ns));
if (!stats)
goto err;
memcpy(stats, tsk->signal->stats, sizeof(*stats));
send:
send_cpu_listeners(rep_skb, listeners);
return;
err:
nlmsg_free(rep_skb);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 107 | 47.35% | 3 | 20.00% |
Oleg Nesterov | 96 | 42.48% | 7 | 46.67% |
Eric W. Biedermann | 18 | 7.96% | 1 | 6.67% |
Jeff Mahoney | 2 | 0.88% | 1 | 6.67% |
Christoph Lameter | 2 | 0.88% | 2 | 13.33% |
Michael Holzheu | 1 | 0.44% | 1 | 6.67% |
Total | 226 | 100.00% | 15 | 100.00% |
static const struct genl_ops taskstats_ops[] = {
{
.cmd = TASKSTATS_CMD_GET,
.doit = taskstats_user_cmd,
.policy = taskstats_cmd_get_policy,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = CGROUPSTATS_CMD_GET,
.doit = cgroupstats_user_cmd,
.policy = cgroupstats_cmd_get_policy,
},
};
static struct genl_family family __ro_after_init = {
.name = TASKSTATS_GENL_NAME,
.version = TASKSTATS_GENL_VERSION,
.maxattr = TASKSTATS_CMD_ATTR_MAX,
.module = THIS_MODULE,
.ops = taskstats_ops,
.n_ops = ARRAY_SIZE(taskstats_ops),
};
/* Needed early in initialization */
void __init taskstats_init_early(void)
{
unsigned int i;
taskstats_cache = KMEM_CACHE(taskstats, SLAB_PANIC);
for_each_possible_cpu(i) {
INIT_LIST_HEAD(&(per_cpu(listener_array, i).list));
init_rwsem(&(per_cpu(listener_array, i).sem));
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 56 | 98.25% | 2 | 66.67% |
Christoph Lameter | 1 | 1.75% | 1 | 33.33% |
Total | 57 | 100.00% | 3 | 100.00% |
static int __init taskstats_init(void)
{
int rc;
rc = genl_register_family(&family);
if (rc)
return rc;
family_registered = 1;
pr_info("registered taskstats version %d\n", TASKSTATS_GENL_VERSION);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 24 | 58.54% | 1 | 20.00% |
Balbir Singh | 12 | 29.27% | 1 | 20.00% |
Johannes Berg | 4 | 9.76% | 2 | 40.00% |
Mandeep Singh Baines | 1 | 2.44% | 1 | 20.00% |
Total | 41 | 100.00% | 5 | 100.00% |
/*
* late initcall ensures initialization of statistics collection
* mechanisms precedes initialization of the taskstats interface
*/
late_initcall(taskstats_init);
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Shailabh Nagar | 1437 | 48.91% | 7 | 11.67% |
Oleg Nesterov | 441 | 15.01% | 10 | 16.67% |
Michael Holzheu | 308 | 10.48% | 2 | 3.33% |
Balbir Singh | 249 | 8.48% | 2 | 3.33% |
Zhang Xiao | 74 | 2.52% | 1 | 1.67% |
Eric W. Biedermann | 71 | 2.42% | 2 | 3.33% |
Johannes Berg | 60 | 2.04% | 5 | 8.33% |
Jeff Mahoney | 49 | 1.67% | 1 | 1.67% |
Rusty Russell | 46 | 1.57% | 1 | 1.67% |
Vasiliy Kulikov | 32 | 1.09% | 1 | 1.67% |
Maxim Uvarov | 32 | 1.09% | 1 | 1.67% |
Chen Gang S | 31 | 1.06% | 2 | 3.33% |
Jay Lan | 19 | 0.65% | 2 | 3.33% |
Alan Cox | 16 | 0.54% | 1 | 1.67% |
Adrian Bunk | 14 | 0.48% | 1 | 1.67% |
Al Viro | 13 | 0.44% | 2 | 3.33% |
Christoph Lameter | 8 | 0.27% | 4 | 6.67% |
Thomas Graf | 7 | 0.24% | 4 | 6.67% |
Arnaldo Carvalho de Melo | 6 | 0.20% | 1 | 1.67% |
Linus Torvalds | 5 | 0.17% | 1 | 1.67% |
Jesper Juhl | 5 | 0.17% | 1 | 1.67% |
Nicolas Dichtel | 4 | 0.14% | 1 | 1.67% |
Tejun Heo | 3 | 0.10% | 1 | 1.67% |
Alexey Dobriyan | 2 | 0.07% | 1 | 1.67% |
Américo Wang | 2 | 0.07% | 1 | 1.67% |
Mandeep Singh Baines | 1 | 0.03% | 1 | 1.67% |
Arun Sharma | 1 | 0.03% | 1 | 1.67% |
Pavel Emelyanov | 1 | 0.03% | 1 | 1.67% |
Robert P. J. Day | 1 | 0.03% | 1 | 1.67% |
Total | 2938 | 100.00% | 60 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.