forked from luck/tmp_suning_uos_patched
[PATCH] taskstats: cleanup do_exit() path
do_exit: taskstats_exit_alloc() ... taskstats_exit_send() taskstats_exit_free() I think this is not good, let it be a single function exported to the core kernel, taskstats_exit(), which does alloc + send + free itself. Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Shailabh Nagar <nagar@watson.ibm.com> Cc: Jay Lan <jlan@engr.sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
128fb95650
commit
115085ea07
|
@ -15,12 +15,6 @@
|
||||||
extern struct kmem_cache *taskstats_cache;
|
extern struct kmem_cache *taskstats_cache;
|
||||||
extern struct mutex taskstats_exit_mutex;
|
extern struct mutex taskstats_exit_mutex;
|
||||||
|
|
||||||
static inline void taskstats_exit_free(struct taskstats *tidstats)
|
|
||||||
{
|
|
||||||
if (tidstats)
|
|
||||||
kmem_cache_free(taskstats_cache, tidstats);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void taskstats_tgid_init(struct signal_struct *sig)
|
static inline void taskstats_tgid_init(struct signal_struct *sig)
|
||||||
{
|
{
|
||||||
sig->stats = NULL;
|
sig->stats = NULL;
|
||||||
|
@ -54,17 +48,10 @@ static inline void taskstats_tgid_free(struct signal_struct *sig)
|
||||||
kmem_cache_free(taskstats_cache, sig->stats);
|
kmem_cache_free(taskstats_cache, sig->stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
|
extern void taskstats_exit(struct task_struct *, int group_dead);
|
||||||
extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int);
|
|
||||||
extern void taskstats_init_early(void);
|
extern void taskstats_init_early(void);
|
||||||
#else
|
#else
|
||||||
static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
|
static inline void taskstats_exit(struct task_struct *tsk, int group_dead)
|
||||||
{}
|
|
||||||
static inline void taskstats_exit_free(struct taskstats *ptidstats)
|
|
||||||
{}
|
|
||||||
static inline void taskstats_exit_send(struct task_struct *tsk,
|
|
||||||
struct taskstats *tidstats,
|
|
||||||
int group_dead, unsigned int cpu)
|
|
||||||
{}
|
{}
|
||||||
static inline void taskstats_tgid_init(struct signal_struct *sig)
|
static inline void taskstats_tgid_init(struct signal_struct *sig)
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -850,9 +850,7 @@ static void exit_notify(struct task_struct *tsk)
|
||||||
fastcall NORET_TYPE void do_exit(long code)
|
fastcall NORET_TYPE void do_exit(long code)
|
||||||
{
|
{
|
||||||
struct task_struct *tsk = current;
|
struct task_struct *tsk = current;
|
||||||
struct taskstats *tidstats;
|
|
||||||
int group_dead;
|
int group_dead;
|
||||||
unsigned int mycpu;
|
|
||||||
|
|
||||||
profile_task_exit(tsk);
|
profile_task_exit(tsk);
|
||||||
|
|
||||||
|
@ -890,8 +888,6 @@ fastcall NORET_TYPE void do_exit(long code)
|
||||||
current->comm, current->pid,
|
current->comm, current->pid,
|
||||||
preempt_count());
|
preempt_count());
|
||||||
|
|
||||||
taskstats_exit_alloc(&tidstats, &mycpu);
|
|
||||||
|
|
||||||
acct_update_integrals(tsk);
|
acct_update_integrals(tsk);
|
||||||
if (tsk->mm) {
|
if (tsk->mm) {
|
||||||
update_hiwater_rss(tsk->mm);
|
update_hiwater_rss(tsk->mm);
|
||||||
|
@ -911,8 +907,8 @@ fastcall NORET_TYPE void do_exit(long code)
|
||||||
#endif
|
#endif
|
||||||
if (unlikely(tsk->audit_context))
|
if (unlikely(tsk->audit_context))
|
||||||
audit_free(tsk);
|
audit_free(tsk);
|
||||||
taskstats_exit_send(tsk, tidstats, group_dead, mycpu);
|
|
||||||
taskstats_exit_free(tidstats);
|
taskstats_exit(tsk, group_dead);
|
||||||
|
|
||||||
exit_mm(tsk);
|
exit_mm(tsk);
|
||||||
|
|
||||||
|
|
|
@ -119,10 +119,10 @@ static int send_reply(struct sk_buff *skb, pid_t pid)
|
||||||
/*
|
/*
|
||||||
* Send taskstats data in @skb to listeners registered for @cpu's exit data
|
* Send taskstats data in @skb to listeners registered for @cpu's exit data
|
||||||
*/
|
*/
|
||||||
static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
|
static void send_cpu_listeners(struct sk_buff *skb,
|
||||||
|
struct listener_list *listeners)
|
||||||
{
|
{
|
||||||
struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
|
struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
|
||||||
struct listener_list *listeners;
|
|
||||||
struct listener *s, *tmp;
|
struct listener *s, *tmp;
|
||||||
struct sk_buff *skb_next, *skb_cur = skb;
|
struct sk_buff *skb_next, *skb_cur = skb;
|
||||||
void *reply = genlmsg_data(genlhdr);
|
void *reply = genlmsg_data(genlhdr);
|
||||||
|
@ -135,7 +135,6 @@ static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
listeners = &per_cpu(listener_array, cpu);
|
|
||||||
down_read(&listeners->sem);
|
down_read(&listeners->sem);
|
||||||
list_for_each_entry(s, &listeners->list, list) {
|
list_for_each_entry(s, &listeners->list, list) {
|
||||||
skb_next = NULL;
|
skb_next = NULL;
|
||||||
|
@ -413,28 +412,12 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
|
|
||||||
{
|
|
||||||
struct listener_list *listeners;
|
|
||||||
/*
|
|
||||||
* This is the cpu on which the task is exiting currently and will
|
|
||||||
* be the one for which the exit event is sent, even if the cpu
|
|
||||||
* on which this function is running changes later.
|
|
||||||
*/
|
|
||||||
*mycpu = raw_smp_processor_id();
|
|
||||||
|
|
||||||
listeners = &per_cpu(listener_array, *mycpu);
|
|
||||||
|
|
||||||
*ptidstats = NULL;
|
|
||||||
if (!list_empty(&listeners->list))
|
|
||||||
*ptidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send pid data out on exit */
|
/* Send pid data out on exit */
|
||||||
void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
|
void taskstats_exit(struct task_struct *tsk, int group_dead)
|
||||||
int group_dead, unsigned int mycpu)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
struct listener_list *listeners;
|
||||||
|
struct taskstats *tidstats;
|
||||||
struct sk_buff *rep_skb;
|
struct sk_buff *rep_skb;
|
||||||
void *reply;
|
void *reply;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -458,12 +441,17 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
|
||||||
fill_tgid_exit(tsk);
|
fill_tgid_exit(tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listeners = &__raw_get_cpu_var(listener_array);
|
||||||
|
if (list_empty(&listeners->list))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
|
||||||
if (!tidstats)
|
if (!tidstats)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
|
rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto ret;
|
goto free_stats;
|
||||||
|
|
||||||
rc = fill_pid(tsk->pid, tsk, tidstats);
|
rc = fill_pid(tsk->pid, tsk, tidstats);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
|
@ -492,15 +480,16 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
|
||||||
nla_nest_end(rep_skb, na);
|
nla_nest_end(rep_skb, na);
|
||||||
|
|
||||||
send:
|
send:
|
||||||
send_cpu_listeners(rep_skb, mycpu);
|
send_cpu_listeners(rep_skb, listeners);
|
||||||
|
free_stats:
|
||||||
|
kmem_cache_free(taskstats_cache, tidstats);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
genlmsg_cancel(rep_skb, reply);
|
genlmsg_cancel(rep_skb, reply);
|
||||||
err_skb:
|
err_skb:
|
||||||
nlmsg_free(rep_skb);
|
nlmsg_free(rep_skb);
|
||||||
ret:
|
goto free_stats;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct genl_ops taskstats_ops = {
|
static struct genl_ops taskstats_ops = {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user