diff options
author | Oleg Nesterov <oleg@redhat.com> | 2015-08-25 20:12:34 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-08-25 21:06:19 -0400 |
commit | 74b22c465cd2b6ff4b8cec3997512ec807e6e495 (patch) | |
tree | bcc0db7d79b2b2c17f6f1cf3743a8eebbebdd7a9 | |
parent | 5cfb203a304deaaa8c7c5368722b214d24583137 (diff) |
params: don't ignore the rest of cmdline if parse_one() fails
parse_args() just aborts after it hits an error, so other args
at the same initcall level are simply ignored. This can lead to
other hard-to-understand problems, for example my testing machine
panics during the boot if I pass "locktorture.verbose=true".
Change parse_args() to save the err code for return and continue.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | kernel/params.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/kernel/params.c b/kernel/params.c index b6554aa71094..ed1e0a1cffa7 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -223,7 +223,7 @@ char *parse_args(const char *doing, | |||
223 | int (*unknown)(char *param, char *val, | 223 | int (*unknown)(char *param, char *val, |
224 | const char *doing, void *arg)) | 224 | const char *doing, void *arg)) |
225 | { | 225 | { |
226 | char *param, *val; | 226 | char *param, *val, *err = NULL; |
227 | 227 | ||
228 | /* Chew leading spaces */ | 228 | /* Chew leading spaces */ |
229 | args = skip_spaces(args); | 229 | args = skip_spaces(args); |
@@ -238,7 +238,7 @@ char *parse_args(const char *doing, | |||
238 | args = next_arg(args, ¶m, &val); | 238 | args = next_arg(args, ¶m, &val); |
239 | /* Stop at -- */ | 239 | /* Stop at -- */ |
240 | if (!val && strcmp(param, "--") == 0) | 240 | if (!val && strcmp(param, "--") == 0) |
241 | return args; | 241 | return err ?: args; |
242 | irq_was_disabled = irqs_disabled(); | 242 | irq_was_disabled = irqs_disabled(); |
243 | ret = parse_one(param, val, doing, params, num, | 243 | ret = parse_one(param, val, doing, params, num, |
244 | min_level, max_level, arg, unknown); | 244 | min_level, max_level, arg, unknown); |
@@ -247,24 +247,25 @@ char *parse_args(const char *doing, | |||
247 | doing, param); | 247 | doing, param); |
248 | 248 | ||
249 | switch (ret) { | 249 | switch (ret) { |
250 | case 0: | ||
251 | continue; | ||
250 | case -ENOENT: | 252 | case -ENOENT: |
251 | pr_err("%s: Unknown parameter `%s'\n", doing, param); | 253 | pr_err("%s: Unknown parameter `%s'\n", doing, param); |
252 | return ERR_PTR(ret); | 254 | break; |
253 | case -ENOSPC: | 255 | case -ENOSPC: |
254 | pr_err("%s: `%s' too large for parameter `%s'\n", | 256 | pr_err("%s: `%s' too large for parameter `%s'\n", |
255 | doing, val ?: "", param); | 257 | doing, val ?: "", param); |
256 | return ERR_PTR(ret); | ||
257 | case 0: | ||
258 | break; | 258 | break; |
259 | default: | 259 | default: |
260 | pr_err("%s: `%s' invalid for parameter `%s'\n", | 260 | pr_err("%s: `%s' invalid for parameter `%s'\n", |
261 | doing, val ?: "", param); | 261 | doing, val ?: "", param); |
262 | return ERR_PTR(ret); | 262 | break; |
263 | } | 263 | } |
264 | |||
265 | err = ERR_PTR(ret); | ||
264 | } | 266 | } |
265 | 267 | ||
266 | /* All parsed OK. */ | 268 | return err; |
267 | return NULL; | ||
268 | } | 269 | } |
269 | 270 | ||
270 | /* Lazy bastard, eh? */ | 271 | /* Lazy bastard, eh? */ |