aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@tv-sign.ru>2006-12-06 23:36:55 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:34 -0500
commit37167485302c8876cb0303af113696e88c2945aa (patch)
tree8bb4cc3eacfe94f56fe9f696f8aede4ac7b2d497
parent51de4d90852ba4cfa5743594ec4a7f158b52dc43 (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>
-rw-r--r--kernel/taskstats.c38
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
71static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, 71static 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
426nla_err:
427 genlmsg_cancel(rep_skb, reply);
428err: 425err:
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
513send: 509send:
514 send_cpu_listeners(rep_skb, listeners); 510 send_cpu_listeners(rep_skb, listeners);
515 return; 511 return;
516 512err:
517nla_err:
518 genlmsg_cancel(rep_skb, reply);
519 nlmsg_free(rep_skb); 513 nlmsg_free(rep_skb);
520} 514}
521 515