diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-12-06 23:36:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:34 -0500 |
commit | 37167485302c8876cb0303af113696e88c2945aa (patch) | |
tree | 8bb4cc3eacfe94f56fe9f696f8aede4ac7b2d497 /kernel | |
parent | 51de4d90852ba4cfa5743594ec4a7f158b52dc43 (diff) |
[PATCH] taskstats: cleanup reply assembling
Thomas Graf wrote:
>
> nla_nest_start() may return NULL, either rely on prepare_reply() to be
> correct and BUG() on failure or do proper error handling for all
> functions.
nla_put() in taskstat.c can fail only if the 'size' argument of alloc_skb()
was not right. This is a kernel bug, we should not hide it. So add 'BUG()'
on error path and check for 'na == NULL'.
> genlmsg_cancel() is only required in error paths for dumping
> procedures.
So we can remove 'genlmsg_cancel()' calls and 'void *reply' (saves 227 bytes).
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Thomas Graf <tgraf@suug.ch>
Cc: Shailabh Nagar <nagar@watson.ibm.com>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Jay Lan <jlan@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/taskstats.c | 38 |
1 files changed, 16 insertions, 22 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index b0aad99c4f8d..4c3476fa058d 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -69,7 +69,7 @@ enum actions { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, | 71 | static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, |
72 | void **replyp, size_t size) | 72 | size_t size) |
73 | { | 73 | { |
74 | struct sk_buff *skb; | 74 | struct sk_buff *skb; |
75 | void *reply; | 75 | void *reply; |
@@ -94,7 +94,6 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, | |||
94 | } | 94 | } |
95 | 95 | ||
96 | *skbp = skb; | 96 | *skbp = skb; |
97 | *replyp = reply; | ||
98 | return 0; | 97 | return 0; |
99 | } | 98 | } |
100 | 99 | ||
@@ -351,11 +350,13 @@ static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid) | |||
351 | struct nlattr *na, *ret; | 350 | struct nlattr *na, *ret; |
352 | int aggr; | 351 | int aggr; |
353 | 352 | ||
354 | aggr = TASKSTATS_TYPE_AGGR_TGID; | 353 | aggr = (type == TASKSTATS_TYPE_PID) |
355 | if (type == TASKSTATS_TYPE_PID) | 354 | ? TASKSTATS_TYPE_AGGR_PID |
356 | aggr = TASKSTATS_TYPE_AGGR_PID; | 355 | : TASKSTATS_TYPE_AGGR_TGID; |
357 | 356 | ||
358 | na = nla_nest_start(skb, aggr); | 357 | na = nla_nest_start(skb, aggr); |
358 | if (!na) | ||
359 | goto err; | ||
359 | if (nla_put(skb, type, sizeof(pid), &pid) < 0) | 360 | if (nla_put(skb, type, sizeof(pid), &pid) < 0) |
360 | goto err; | 361 | goto err; |
361 | ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats)); | 362 | ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats)); |
@@ -373,7 +374,6 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | |||
373 | int rc = 0; | 374 | int rc = 0; |
374 | struct sk_buff *rep_skb; | 375 | struct sk_buff *rep_skb; |
375 | struct taskstats *stats; | 376 | struct taskstats *stats; |
376 | void *reply; | ||
377 | size_t size; | 377 | size_t size; |
378 | cpumask_t mask; | 378 | cpumask_t mask; |
379 | 379 | ||
@@ -395,7 +395,7 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | |||
395 | size = nla_total_size(sizeof(u32)) + | 395 | size = nla_total_size(sizeof(u32)) + |
396 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); | 396 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); |
397 | 397 | ||
398 | rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); | 398 | rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size); |
399 | if (rc < 0) | 399 | if (rc < 0) |
400 | return rc; | 400 | return rc; |
401 | 401 | ||
@@ -404,27 +404,24 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | |||
404 | u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); | 404 | u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); |
405 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid); | 405 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid); |
406 | if (!stats) | 406 | if (!stats) |
407 | goto nla_err; | 407 | goto err; |
408 | 408 | ||
409 | rc = fill_pid(pid, NULL, stats); | 409 | rc = fill_pid(pid, NULL, stats); |
410 | if (rc < 0) | 410 | if (rc < 0) |
411 | goto nla_err; | 411 | goto err; |
412 | } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { | 412 | } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { |
413 | u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); | 413 | u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); |
414 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid); | 414 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid); |
415 | if (!stats) | 415 | if (!stats) |
416 | goto nla_err; | 416 | goto err; |
417 | 417 | ||
418 | rc = fill_tgid(tgid, NULL, stats); | 418 | rc = fill_tgid(tgid, NULL, stats); |
419 | if (rc < 0) | 419 | if (rc < 0) |
420 | goto nla_err; | 420 | goto err; |
421 | } else | 421 | } else |
422 | goto err; | 422 | goto err; |
423 | 423 | ||
424 | return send_reply(rep_skb, info->snd_pid); | 424 | return send_reply(rep_skb, info->snd_pid); |
425 | |||
426 | nla_err: | ||
427 | genlmsg_cancel(rep_skb, reply); | ||
428 | err: | 425 | err: |
429 | nlmsg_free(rep_skb); | 426 | nlmsg_free(rep_skb); |
430 | return rc; | 427 | return rc; |
@@ -461,7 +458,6 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
461 | struct listener_list *listeners; | 458 | struct listener_list *listeners; |
462 | struct taskstats *stats; | 459 | struct taskstats *stats; |
463 | struct sk_buff *rep_skb; | 460 | struct sk_buff *rep_skb; |
464 | void *reply; | ||
465 | size_t size; | 461 | size_t size; |
466 | int is_thread_group; | 462 | int is_thread_group; |
467 | 463 | ||
@@ -486,17 +482,17 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
486 | if (list_empty(&listeners->list)) | 482 | if (list_empty(&listeners->list)) |
487 | return; | 483 | return; |
488 | 484 | ||
489 | rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); | 485 | rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, size); |
490 | if (rc < 0) | 486 | if (rc < 0) |
491 | return; | 487 | return; |
492 | 488 | ||
493 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid); | 489 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid); |
494 | if (!stats) | 490 | if (!stats) |
495 | goto nla_err; | 491 | goto err; |
496 | 492 | ||
497 | rc = fill_pid(tsk->pid, tsk, stats); | 493 | rc = fill_pid(tsk->pid, tsk, stats); |
498 | if (rc < 0) | 494 | if (rc < 0) |
499 | goto nla_err; | 495 | goto err; |
500 | 496 | ||
501 | /* | 497 | /* |
502 | * Doesn't matter if tsk is the leader or the last group member leaving | 498 | * Doesn't matter if tsk is the leader or the last group member leaving |
@@ -506,16 +502,14 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
506 | 502 | ||
507 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid); | 503 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid); |
508 | if (!stats) | 504 | if (!stats) |
509 | goto nla_err; | 505 | goto err; |
510 | 506 | ||
511 | memcpy(stats, tsk->signal->stats, sizeof(*stats)); | 507 | memcpy(stats, tsk->signal->stats, sizeof(*stats)); |
512 | 508 | ||
513 | send: | 509 | send: |
514 | send_cpu_listeners(rep_skb, listeners); | 510 | send_cpu_listeners(rep_skb, listeners); |
515 | return; | 511 | return; |
516 | 512 | err: | |
517 | nla_err: | ||
518 | genlmsg_cancel(rep_skb, reply); | ||
519 | nlmsg_free(rep_skb); | 513 | nlmsg_free(rep_skb); |
520 | } | 514 | } |
521 | 515 | ||