aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2013-07-03 18:08:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:08:02 -0400
commit3ceadcf6d489650ade673b7197c11c521aecb038 (patch)
treee9c0e9a77cc28d9a8040b41f5699b9da4556fb0c
parent923bed030ff6e20b5176e10da151fade83097891 (diff)
coredump: kill call_count, add core_name_size
Imho, "atomic_t call_count" is ugly and should die. It buys nothing and in fact it can grow more than necessary, expand doesn't check if it was already incremented by another task. Kill it, and introduce "static int core_name_size" updated by expand_corename(). This is obviously racy too but harmless, and core_name_size never grows for no reason. We do not bother to to calculate the "right" new size, we simply do kmalloc(size_we_need) and use ksize() to rely on kmalloc_index's decision. Finally change format_corename() to use expand_corename(), krealloc(NULL) is fine. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Colin Walters <walters@verbum.org> Cc: Denys Vlasenko <vda.linux@googlemail.com> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Lennart Poettering <mzxreary@0pointer.de> Cc: Lucas De Marchi <lucas.de.marchi@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/coredump.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/fs/coredump.c b/fs/coredump.c
index 90d7cee54347..56a9ab963a40 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -45,26 +45,28 @@
45#include <trace/events/sched.h> 45#include <trace/events/sched.h>
46 46
47int core_uses_pid; 47int core_uses_pid;
48char core_pattern[CORENAME_MAX_SIZE] = "core";
49unsigned int core_pipe_limit; 48unsigned int core_pipe_limit;
49char core_pattern[CORENAME_MAX_SIZE] = "core";
50static int core_name_size = CORENAME_MAX_SIZE;
50 51
51struct core_name { 52struct core_name {
52 char *corename; 53 char *corename;
53 int used, size; 54 int used, size;
54}; 55};
55static atomic_t call_count = ATOMIC_INIT(1);
56 56
57/* The maximal length of core_pattern is also specified in sysctl.c */ 57/* The maximal length of core_pattern is also specified in sysctl.c */
58 58
59static int expand_corename(struct core_name *cn) 59static int expand_corename(struct core_name *cn, int size)
60{ 60{
61 int size = CORENAME_MAX_SIZE * atomic_inc_return(&call_count);
62 char *corename = krealloc(cn->corename, size, GFP_KERNEL); 61 char *corename = krealloc(cn->corename, size, GFP_KERNEL);
63 62
64 if (!corename) 63 if (!corename)
65 return -ENOMEM; 64 return -ENOMEM;
66 65
67 cn->size = size; 66 if (size > core_name_size) /* racy but harmless */
67 core_name_size = size;
68
69 cn->size = ksize(corename);
68 cn->corename = corename; 70 cn->corename = corename;
69 return 0; 71 return 0;
70} 72}
@@ -81,7 +83,7 @@ again:
81 return 0; 83 return 0;
82 } 84 }
83 85
84 if (!expand_corename(cn)) 86 if (!expand_corename(cn, cn->size + need - free + 1))
85 goto again; 87 goto again;
86 88
87 return -ENOMEM; 89 return -ENOMEM;
@@ -160,9 +162,8 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
160 int err = 0; 162 int err = 0;
161 163
162 cn->used = 0; 164 cn->used = 0;
163 cn->size = CORENAME_MAX_SIZE * atomic_read(&call_count); 165 cn->corename = NULL;
164 cn->corename = kmalloc(cn->size, GFP_KERNEL); 166 if (expand_corename(cn, core_name_size))
165 if (!cn->corename)
166 return -ENOMEM; 167 return -ENOMEM;
167 168
168 /* Repeat as long as we have more pattern to process and more output 169 /* Repeat as long as we have more pattern to process and more output