This patch adds an option "--reuse-cmdline" for people that are lazy in typing --append="$(cat /proc/cmdline)". The advantage of "--reuse-cmdline" is also that it strips off BOOT_IMAGE (since it may not be correct any more) from lilo and other boot loaders, and, more important, the crashkernel option in case a panic kernel is loaded. If you like the option I can also add it for really all architectures. Tested only with x86-bzImage both the kexec and kdump case. Signed-off-by: Bernhard Walle <bwalle at suse.de> --- kexec/arch/i386/kexec-bzImage.c | 12 +++- kexec/arch/i386/kexec-elf-x86.c | 16 ++++-- kexec/arch/i386/kexec-multiboot-x86.c | 12 +++- kexec/arch/x86_64/kexec-elf-x86_64.c | 16 ++++-- kexec/kexec.8 | 18 +++++++ kexec/kexec.c | 85 +++++++++++++++++++++++++++++----- kexec/kexec.h | 1 7 files changed, 132 insertions(+), 28 deletions(-) --- a/kexec/arch/i386/kexec-bzImage.c +++ b/kexec/arch/i386/kexec-bzImage.c @@ -89,6 +89,7 @@ void bzImage_usage(void) " --real-mode Use the kernels real mode entry point.\n" " --command-line=STRING Set the kernel command line to STRING.\n" " --append=STRING Set the kernel command line to STRING.\n" + " --reuse-cmdline Use kernel command line from running system.\n" " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n" " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n" ); @@ -335,14 +336,16 @@ int bzImage_load(int argc, char **argv, int debug, real_mode_entry; int opt; int result; -#define OPT_APPEND (OPT_ARCH_MAX+0) -#define OPT_RAMDISK (OPT_ARCH_MAX+1) -#define OPT_REAL_MODE (OPT_ARCH_MAX+2) +#define OPT_APPEND (OPT_ARCH_MAX+0) +#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1) +#define OPT_RAMDISK (OPT_ARCH_MAX+2) +#define OPT_REAL_MODE (OPT_ARCH_MAX+3) static const struct option options[] = { KEXEC_ARCH_OPTIONS { "debug", 0, 0, OPT_DEBUG }, { "command-line", 1, 0, OPT_APPEND }, { "append", 1, 0, OPT_APPEND }, + { "reuse-cmdline", 1, 0, OPT_REUSE_CMDLINE }, { "initrd", 1, 0, OPT_RAMDISK }, { "ramdisk", 1, 0, OPT_RAMDISK }, { "real-mode", 0, 0, OPT_REAL_MODE }, @@ -374,6 +377,9 @@ int bzImage_load(int argc, char **argv, case OPT_APPEND: command_line = optarg; break; + case OPT_REUSE_CMDLINE: + command_line = get_command_line(); + break; case OPT_RAMDISK: ramdisk = optarg; break; --- a/kexec/arch/i386/kexec-elf-x86.c +++ b/kexec/arch/i386/kexec-elf-x86.c @@ -73,6 +73,7 @@ void elf_x86_usage(void) { printf( " --command-line=STRING Set the kernel command line to STRING\n" " --append=STRING Set the kernel command line to STRING\n" + " --reuse-cmdline Use kernel command line from running system.\n" " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n" " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n" " --args-linux Pass linux kernel style options\n" @@ -97,16 +98,18 @@ int elf_x86_load(int argc, char **argv, #define ARG_STYLE_LINUX 1 #define ARG_STYLE_NONE 2 int opt; -#define OPT_APPEND (OPT_ARCH_MAX+0) -#define OPT_RAMDISK (OPT_ARCH_MAX+1) -#define OPT_ARGS_ELF (OPT_ARCH_MAX+2) -#define OPT_ARGS_LINUX (OPT_ARCH_MAX+3) -#define OPT_ARGS_NONE (OPT_ARCH_MAX+4) +#define OPT_APPEND (OPT_ARCH_MAX+0) +#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1) +#define OPT_RAMDISK (OPT_ARCH_MAX+2) +#define OPT_ARGS_ELF (OPT_ARCH_MAX+3) +#define OPT_ARGS_LINUX (OPT_ARCH_MAX+4) +#define OPT_ARGS_NONE (OPT_ARCH_MAX+5) static const struct option options[] = { KEXEC_ARCH_OPTIONS { "command-line", 1, NULL, OPT_APPEND }, { "append", 1, NULL, OPT_APPEND }, + { "reuse-cmdline", 1, NULL, OPT_REUSE_CMDLINE }, { "initrd", 1, NULL, OPT_RAMDISK }, { "ramdisk", 1, NULL, OPT_RAMDISK }, { "args-elf", 0, NULL, OPT_ARGS_ELF }, @@ -138,6 +141,9 @@ int elf_x86_load(int argc, char **argv, case OPT_APPEND: command_line = optarg; break; + case OPT_REUSE_CMDLINE: + command_line = get_command_line(); + break; case OPT_RAMDISK: ramdisk = optarg; break; --- a/kexec/arch/i386/kexec-multiboot-x86.c +++ b/kexec/arch/i386/kexec-multiboot-x86.c @@ -129,6 +129,7 @@ void multiboot_x86_usage(void) /* Multiboot-specific options */ { printf(" --command-line=STRING Set the kernel command line to STRING.\n"); + printf(" --reuse-cmdline Use kernel command line from running system.\n"); printf(" --module=\"MOD arg1 arg2...\" Load module MOD with command-line \"arg1...\"\n"); printf(" (can be used multiple times).\n"); } @@ -155,13 +156,15 @@ int multiboot_x86_load(int argc, char ** int i; int opt; int modules, mod_command_line_space; -#define OPT_CL (OPT_ARCH_MAX+0) -#define OPT_MOD (OPT_ARCH_MAX+1) -#define OPT_VGA (OPT_ARCH_MAX+2) +#define OPT_CL (OPT_ARCH_MAX+0) +#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1) +#define OPT_MOD (OPT_ARCH_MAX+2) +#define OPT_VGA (OPT_ARCH_MAX+3) static const struct option options[] = { KEXEC_ARCH_OPTIONS { "command-line", 1, 0, OPT_CL }, { "append", 1, 0, OPT_CL }, + { "reuse-cmdline", 1, 0, OPT_REUSE_CMDLINE }, { "module", 1, 0, OPT_MOD }, { 0, 0, 0, 0 }, }; @@ -194,6 +197,9 @@ int multiboot_x86_load(int argc, char ** case OPT_CL: command_line = optarg; break; + case OPT_REUSE_CMDLINE: + command_line = get_command_line(); + break; case OPT_MOD: modules++; mod_command_line_space += strlen(optarg) + 1; --- a/kexec/arch/x86_64/kexec-elf-x86_64.c +++ b/kexec/arch/x86_64/kexec-elf-x86_64.c @@ -73,6 +73,7 @@ void elf_x86_64_usage(void) { printf( " --command-line=STRING Set the kernel command line to STRING\n" " --append=STRING Set the kernel command line to STRING\n" + " --reuse-cmdline Use kernel command line from running system.\n" " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n" " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n" " --args-linux Pass linux kernel style options\n" @@ -96,16 +97,18 @@ int elf_x86_64_load(int argc, char **arg #define ARG_STYLE_LINUX 1 #define ARG_STYLE_NONE 2 int opt; -#define OPT_APPEND (OPT_ARCH_MAX+0) -#define OPT_RAMDISK (OPT_ARCH_MAX+1) -#define OPT_ARGS_ELF (OPT_ARCH_MAX+2) -#define OPT_ARGS_LINUX (OPT_ARCH_MAX+3) -#define OPT_ARGS_NONE (OPT_ARCH_MAX+4) +#define OPT_APPEND (OPT_ARCH_MAX+0) +#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1) +#define OPT_RAMDISK (OPT_ARCH_MAX+2) +#define OPT_ARGS_ELF (OPT_ARCH_MAX+3) +#define OPT_ARGS_LINUX (OPT_ARCH_MAX+4) +#define OPT_ARGS_NONE (OPT_ARCH_MAX+5) static const struct option options[] = { KEXEC_ARCH_OPTIONS { "command-line", 1, NULL, OPT_APPEND }, { "append", 1, NULL, OPT_APPEND }, + { "reuse-cmdline", 1, NULL, OPT_REUSE_CMDLINE }, { "initrd", 1, NULL, OPT_RAMDISK }, { "ramdisk", 1, NULL, OPT_RAMDISK }, { "args-elf", 0, NULL, OPT_ARGS_ELF }, @@ -138,6 +141,9 @@ int elf_x86_64_load(int argc, char **arg case OPT_APPEND: command_line = optarg; break; + case OPT_REUSE_CMDLINE: + command_line = get_command_line(); + break; case OPT_RAMDISK: ramdisk = optarg; break; --- a/kexec/kexec.8 +++ b/kexec/kexec.8 @@ -186,6 +186,15 @@ to the kernel command line. Set the kernel command line to .IR string . .TP +.BI \-\-reuse-cmdline +Use the command line from the running system. When a panic kernel is loaded, it +strips the +.I +crashkernel +parameter automatically. The +.I BOOT_IMAGE +parameter is also stripped. +.TP .BI \-\-initrd= file Use .I file @@ -204,6 +213,15 @@ as the kernel's initial ramdisk. Set the kernel command line to .IR string . .TP +.BI \-\-reuse-cmdline +Use the command line from the running system. When a panic kernel is loaded, it +strips the +.I +crashkernel +parameter automatically. The +.I BOOT_IMAGE +parameter is also stripped. +.TP .BI \-\-module= "mod arg1 arg2 ..." Load module .I mod --- a/kexec/kexec.c +++ b/kexec/kexec.c @@ -31,6 +31,7 @@ #include <unistd.h> #include <fcntl.h> #include <getopt.h> +#include <ctype.h> #include "config.h" @@ -46,6 +47,7 @@ unsigned long long mem_min = 0; unsigned long long mem_max = ULONG_MAX; +unsigned long kexec_flags = 0; void die(char *fmt, ...) { @@ -792,26 +794,86 @@ static int kexec_loaded(void) return ret; } +/* + * Remove parameter from a kernel command line. Helper function by get_command_line(). + */ +static void remove_parameter(char *line, const char *param_name) +{ + char *start, *end; + + start = strstr(line, param_name); + + /* parameter not found */ + if (!start) + return; + + /* + * check if that's really the start of a parameter and not in + * the middle of the word + */ + if (start != line && !isspace(*(start-1))) + return; + + end = strstr(start, " "); + if (!end) + *start = 0; + else { + memmove(start, end+1, strlen(end)); + *(end + strlen(end)) = 0; + } +} + +/* + * Returns the contents of the current command line to be used with + * --reuse-cmdline option. The function gets called from architecture specific + * code. If we load a panic kernel, that function will strip the + * "crashkernel=" option because it does not make sense that the crashkernel + * reserves memory for a crashkernel (well, it would not boot since the + * amount is exactly the same as the crashkernel has overall memory). Also, + * remove the BOOT_IMAGE from lilo (and others) since that doesn't make + * sense here any more. The kernel could be different even if we reuse the + * commandline. + * + * The function returns dynamically allocated memory. + */ +char *get_command_line(void) +{ + FILE *fp; + size_t len; + char *line = NULL; + + fp = fopen("/proc/cmdline", "r"); + if (!fp) + die("Could not read /proc/cmdline."); + getline(&line, &len, fp); + fclose(fp); + + if (line) { + /* strip newline */ + *(line + strlen(line) - 1) = 0; + + remove_parameter(line, "crashkernel"); + if (kexec_flags & KEXEC_ON_CRASH) + remove_parameter(line, "BOOT_IMAGE"); + } else + line = strdup(""); + + return line; +} + /* check we retained the initrd */ void check_reuse_initrd(void) { - FILE * fp; - char * line = NULL; - size_t len = 0; - ssize_t read; + char *line = get_command_line(); - fp = fopen("/proc/cmdline", "r"); - if (fp == NULL) - die("unable to open /proc/cmdline\n"); - read = getline(&line, &len, fp); if (strstr(line, "retain_initrd") == NULL) die("unrecoverable error: current boot didn't " "retain the initrd for reuse.\n"); - if (line) - free(line); - fclose(fp); + + free(line); } + int main(int argc, char *argv[]) { int do_load = 1; @@ -821,7 +883,6 @@ int main(int argc, char *argv[]) int do_ifdown = 0; int do_unload = 0; int do_reuse_initrd = 0; - unsigned long kexec_flags = 0; char *type = 0; char *endptr; int opt; --- a/kexec/kexec.h +++ b/kexec/kexec.h @@ -220,6 +220,7 @@ int arch_process_options(int argc, char int arch_compat_trampoline(struct kexec_info *info); void arch_update_purgatory(struct kexec_info *info); int is_crashkernel_mem_reserved(void); +char *get_command_line(void); int kexec_iomem_for_each_line(char *match, int (*callback)(void *data,