X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=kernel%2Ftaskstats.c;h=4c3476fa058d5627650779f0559dc17c3a7cb1b8;hb=2fb90b128aaf7758e3de22119515fb11174d4f23;hp=d2a41339f37bd0b7722aba407ca04e98c372660d;hpb=68062b86fc0f480b806d270a8278709a5a41bb67;p=linux-2.6 diff --git a/kernel/taskstats.c b/kernel/taskstats.c index d2a41339f3..4c3476fa05 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -69,7 +69,7 @@ enum actions { }; static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, - void **replyp, size_t size) + size_t size) { struct sk_buff *skb; void *reply; @@ -94,7 +94,6 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, } *skbp = skb; - *replyp = reply; return 0; } @@ -185,6 +184,7 @@ static int fill_pid(pid_t pid, struct task_struct *tsk, } else get_task_struct(tsk); + memset(stats, 0, sizeof(*stats)); /* * Each accounting subsystem adds calls to its functions to * fill in relevant parts of struct taskstsats as follows @@ -227,6 +227,8 @@ static int fill_tgid(pid_t tgid, struct task_struct *first, if (first->signal->stats) memcpy(stats, first->signal->stats, sizeof(*stats)); + else + memset(stats, 0, sizeof(*stats)); tsk = first; do { @@ -343,31 +345,35 @@ static int parse(struct nlattr *na, cpumask_t *mask) return ret; } -static int mk_reply(struct sk_buff *skb, int type, u32 pid, struct taskstats *stats) +static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid) { - struct nlattr *na; + struct nlattr *na, *ret; int aggr; - aggr = TASKSTATS_TYPE_AGGR_TGID; - if (type == TASKSTATS_TYPE_PID) - aggr = TASKSTATS_TYPE_AGGR_PID; + aggr = (type == TASKSTATS_TYPE_PID) + ? TASKSTATS_TYPE_AGGR_PID + : TASKSTATS_TYPE_AGGR_TGID; na = nla_nest_start(skb, aggr); - NLA_PUT_U32(skb, type, pid); - NLA_PUT_TYPE(skb, struct taskstats, TASKSTATS_TYPE_STATS, *stats); + if (!na) + goto err; + if (nla_put(skb, type, sizeof(pid), &pid) < 0) + goto err; + ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats)); + if (!ret) + goto err; nla_nest_end(skb, na); - return 0; -nla_put_failure: - return -1; + return nla_data(ret); +err: + return NULL; } static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) { int rc = 0; struct sk_buff *rep_skb; - struct taskstats stats; - void *reply; + struct taskstats *stats; size_t size; cpumask_t mask; @@ -389,36 +395,33 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) size = nla_total_size(sizeof(u32)) + nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); - memset(&stats, 0, sizeof(stats)); - rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); + rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size); if (rc < 0) return rc; + rc = -EINVAL; if (info->attrs[TASKSTATS_CMD_ATTR_PID]) { u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); - rc = fill_pid(pid, NULL, &stats); - if (rc < 0) + stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid); + if (!stats) goto err; - if (mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid, &stats)) - goto nla_put_failure; + rc = fill_pid(pid, NULL, stats); + if (rc < 0) + goto err; } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); - rc = fill_tgid(tgid, NULL, &stats); - if (rc < 0) + stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid); + if (!stats) goto err; - if (mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid, &stats)) - goto nla_put_failure; - } else { - rc = -EINVAL; + rc = fill_tgid(tgid, NULL, stats); + if (rc < 0) + goto err; + } else goto err; - } return send_reply(rep_skb, info->snd_pid); - -nla_put_failure: - rc = genlmsg_cancel(rep_skb, reply); err: nlmsg_free(rep_skb); return rc; @@ -453,9 +456,8 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) { int rc; struct listener_list *listeners; - struct taskstats *tidstats; + struct taskstats *stats; struct sk_buff *rep_skb; - void *reply; size_t size; int is_thread_group; @@ -480,20 +482,17 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) if (list_empty(&listeners->list)) return; - tidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); - if (!tidstats) + rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, size); + if (rc < 0) return; - rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); - if (rc < 0) - goto free_stats; + stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid); + if (!stats) + goto err; - rc = fill_pid(tsk->pid, tsk, tidstats); + rc = fill_pid(tsk->pid, tsk, stats); if (rc < 0) - goto err_skb; - - if (mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid, tidstats)) - goto nla_put_failure; + goto err; /* * Doesn't matter if tsk is the leader or the last group member leaving @@ -501,20 +500,17 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) if (!is_thread_group || !group_dead) goto send; - if (mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid, tsk->signal->stats)) - goto nla_put_failure; + stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid); + if (!stats) + goto err; + + memcpy(stats, tsk->signal->stats, sizeof(*stats)); send: send_cpu_listeners(rep_skb, listeners); -free_stats: - kmem_cache_free(taskstats_cache, tidstats); return; - -nla_put_failure: - genlmsg_cancel(rep_skb, reply); -err_skb: +err: nlmsg_free(rep_skb); - goto free_stats; } static struct genl_ops taskstats_ops = {