[PATCH] makedumpfile: make --work-dir easier to use

Cliff Wickman cpw at sgi.com
Wed Sep 9 18:17:40 PDT 2015


Hello Kumagai,

On Wed, Sep 09, 2015 at 07:51:50AM +0000, Atsushi Kumagai wrote:
> Hello Cliff,
> 
> >From: Cliff Wickman <cpw at sgi.com>
> >
> >This patch enhances the --work-dir feature to make it easier to use.
> >
> >Kumagai, I plan to require the --work-dir for the -e feature, as you suggested.  I did find --work-dir
> >hard to implement because of the differences between the way the various distros mount the root device
> >in the crashkernel. Hence this patch.
> >
> >Currently the --work-dir=<PATH> must be specified in a form that is valid in the crashkernel's environment.
> >In other words, the boot kernel's /var, for example, must be specified as:
> >  RHEL6: /mnt/var/
> >  RHEL7: /sysroot/var/
> >  SLES11: /kdump/0/var/
> >  SLES12: (with root=kdump) /kdump/mnt0/var/
> >And the administrator must remember to create that directory.
> >
> >If these conditions are not met makedumpfile fails, with little explanation as to why.
> >
> >This patch:
> >
> >- Allow the path to be one that is valid in the crashkernel's environment, or allow
> >  it to be valid in the boot kernel's environment.  In the second case, adjust the path to
> >  how the root device is mounted in the crashkernel.
> >  Limitation: The adjustment is only made if a dump file is being written, and the dump is
> >  being written to /var/crash/.  Otherwise you must (as currently) use a path that is known
> >  to be valid in the crashkernel's environment.
> >
> >- Make the directory if it does not already exist.  All components of the path are
> >  made if necessary, similar to mkdir -p.
> 
> I think such adjusting should be done in kdump feature side (e.g. kexec-tools) since
> it constructs the crash kernel's environment. Each distro's kdump feature can
> take care of each own environment.

> Just checking by is_dir() and creating a directory are enough in makedumpfile side.
> 
> Thanks,
> Atsushi Kumagai

I have been looking at how this could be done.
As each distro may mount the root filesystem differently, it would seem to me that
the name must be passed to makedumpfile somehow.  I don't see kexec having a role but
the scripts that make the kdump initrd could.
Am I missing your point in concluding that?

One could add another option to makedumpfile (maybe --root=<path>).  And then the distro's
scripts could add that option to the makedumpfile command line. But that turns out to be
difficult to do in SLES, as it has its own binary named 'kdumptool' that invokes
makedumpfile and it does not have a way to pass an option to makedumpfile
that is derived at mkdumprd time.  It only passes along options that have been stored
in /etc/sysconfig/kdump.

Deriving the root path from the dump name is not very reliable if it depends on a
convention that could change.
What is configured in the kdump or kdump.conf file is the "/var/crash" or similar dump
file directory.
I propose to add a --dump-dir option to makedumpfile. The distro script can easily
add --dump-dir=/var/crash to the command line, and then the path to root can be
accurately derived.  If --dump-dir is not specified then --work-dir would have to
be pre-adjusted, as it is currently.

-Cliff
> 
> >---
> > makedumpfile.c |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > makedumpfile.h |    3 -
> > print_info.c   |   15 ++++-
> > 3 files changed, 158 insertions(+), 4 deletions(-)
> >
> >Index: code/makedumpfile.c
> >===================================================================
> >--- code.orig/makedumpfile.c
> >+++ code/makedumpfile.c
> >@@ -25,6 +25,7 @@
> > #include <sys/time.h>
> > #include <limits.h>
> > #include <assert.h>
> >+#include <sys/stat.h>
> >
> > struct symbol_table	symbol_table;
> > struct size_table	size_table;
> >@@ -10364,6 +10365,146 @@ int show_mem_usage(void)
> > 	return TRUE;
> > }
> >
> >+/*
> >+ * return 1 if path is a directory
> >+ * else return 0
> >+ */
> >+int
> >+isdir(char *path)
> >+{
> >+	struct stat buf;
> >+
> >+	if (path) {
> >+		if (stat(path, &buf) || !S_ISDIR(buf.st_mode)) {
> >+			return 0;
> >+		}
> >+		return 1;
> >+	} else {
> >+		return 0;
> >+	}
> >+}
> >+
> >+/*
> >+ * Set info->root_dir to the crashkernel's path to the bootkernel's root
> >+ * or set it to null if that path cannot be determined.
> >+ * We must assume that the dump file is in the bootkernel's /var/crash/
> >+ */
> >+void
> >+set_rootdir()
> >+{
> >+	int len;
> >+	char *cp1, *cp2;
> >+
> >+	/* allow this function to be called multiple times */
> >+	if (info->root_dir)
> >+		return;
> >+
> >+	if (!info->name_dumpfile) {
> >+		info->root_dir = NULL;
> >+		return;
> >+	}
> >+
> >+	len = (int)strlen(info->name_dumpfile);
> >+	if (len == 0) {
> >+		info->root_dir = NULL;
> >+		return;
> >+	}
> >+	info->root_dir = malloc(len);
> >+	cp1 = info->name_dumpfile;
> >+	cp2 = cp1;
> >+	while (*cp2 != '\0') {
> >+		if (!strncmp(cp2, "/var/crash/", 11)) {
> >+			len = cp2 - cp1;
> >+			strncpy(info->root_dir, cp1, len);
> >+			if (!isdir(info->root_dir)) {
> >+				fprintf(stderr, "Error: root directory %s does not exist\n",
> >+					info->root_dir);
> >+				exit(1);
> >+			}
> >+			return;
> >+		}
> >+		cp2++;
> >+	}
> >+	info->root_dir = NULL;
> >+	return;
> >+}
> >+
> >+/*
> >+ * The --work-dir directory should be validated and created if necessary.
> >+ */
> >+void
> >+adjust_working_dir()
> >+{
> >+	int ret, finished=0;
> >+	char *hold, *inter_dir = NULL, *cp1, *cp2;
> >+
> >+	/* if a crashkernel root environment was specified, no adjust is necessary */
> >+	if (isdir(info->working_dir))
> >+		return;
> >+
> >+	set_rootdir();
> >+
> >+	if (!strncmp(info->working_dir, "/", 1)) {
> >+		/* an absolute path should either exist in the crashkernel's
> >+		   root, or should be adjusted to be relative to it */
> >+		if (info->root_dir) {
> >+			hold = malloc(strlen(info->working_dir)+1);
> >+			strcpy(hold, info->working_dir);
> >+			info->working_dir = malloc(strlen(info->root_dir) + strlen(info->working_dir));
> >+			inter_dir = malloc(strlen(info->root_dir) + strlen(info->working_dir));
> >+			strcpy(info->working_dir, info->root_dir);
> >+			strcat(info->working_dir, hold);
> >+			free (hold);
> >+			fprintf(stderr, "--workdir set to %s\n", info->working_dir);
> >+		} else {
> >+			inter_dir = malloc(strlen(info->working_dir));
> >+		}
> >+	} else {
> >+		/* a relative path that does not already exist should be made absolute; it is taken to
> >+		   be relative to the crash kernel's root */
> >+		if (info->root_dir) {
> >+			hold = malloc(strlen(info->working_dir)+1);
> >+			strcpy(hold, info->working_dir);
> >+			info->working_dir = malloc(strlen(info->root_dir) + strlen(info->working_dir) + 1);
> >+			inter_dir = malloc(strlen(info->root_dir) + strlen(info->working_dir) + 1);
> >+			strcpy(info->working_dir, info->root_dir);
> >+			strcat(info->working_dir, "/");
> >+			strcat(info->working_dir, hold);
> >+			free (hold);
> >+			fprintf(stderr, "--workdir set to %s\n", info->working_dir);
> >+		} else {
> >+			inter_dir = malloc(strlen(info->working_dir));
> >+		}
> >+	}
> >+
> >+	/* path is complete, now make sure it exists */
> >+	if (!isdir(info->working_dir)) {
> >+		strcpy(inter_dir, info->working_dir);
> >+		if (info->root_dir)
> >+			cp1 = inter_dir + strlen(info->root_dir) + 1;
> >+		else
> >+			cp1 = inter_dir + 1;
> >+		while (finished == 0) {
> >+			strcpy(inter_dir, info->working_dir);
> >+			cp2 = strchr(cp1, '/');
> >+			if (cp2) {
> >+				*cp2 = '\0';
> >+				cp1 = cp2 + 1;
> >+			} else {
> >+				finished = 1;
> >+			}
> >+			if (!isdir(inter_dir)) {
> >+				ret = mkdir(inter_dir, 0755);
> >+				if (ret) {
> >+					fprintf(stderr, "Error: mkdir(%s, 0755) returned %d\n",
> >+						inter_dir, ret);
> >+					exit(1);
> >+				}
> >+			}
> >+		}
> >+	}
> >+	return;
> >+}
> >
> > static struct option longopts[] = {
> > 	{"split", no_argument, NULL, OPT_SPLIT},
> >@@ -10549,6 +10690,9 @@ main(int argc, char *argv[])
> > 		return COMPLETED;
> > 	}
> >
> >+	if (info->working_dir)
> >+		adjust_working_dir();
> >+
> > 	if (elf_version(EV_CURRENT) == EV_NONE ) {
> > 		/*
> > 		 * library out of date
> >Index: code/makedumpfile.h
> >===================================================================
> >--- code.orig/makedumpfile.h
> >+++ code/makedumpfile.h
> >@@ -1258,7 +1258,8 @@ struct DumpInfo {
> > 	/*
> > 	 * for cyclic processing
> > 	 */
> >-	char	           *working_dir;	     /* working directory for bitmap */
> >+	char	           *working_dir;	/* working directory for bitmap */
> >+	char	           *root_dir;		/* crashkernel path to boot kernel's root */
> > 	mdf_pfn_t          num_dumpable;
> > 	unsigned long      bufsize_cyclic;
> > 	unsigned long      pfn_cyclic;
> >Index: code/print_info.c
> >===================================================================
> >--- code.orig/print_info.c
> >+++ code/print_info.c
> >@@ -221,11 +221,20 @@ print_usage(void)
> > 	MSG("      size is at most N kilo bytes.\n");
> > 	MSG("\n");
> > 	MSG("  [--work-dir]:\n");
> >-	MSG("      Specify the working directory for the temporary bitmap file.\n");
> >-	MSG("      If this option isn't specified, the bitmap will be saved on memory.\n");
> >+	MSG("      Specify the working directory for temporary files such as the bitmap.\n");
> >+	MSG("      If this option isn't specified, the bitmap will be saved in memory.\n");
> > 	MSG("      Filtering processing has to do 2 pass scanning to fix the memory consumption,\n");
> >-	MSG("      but it can be avoided by using working directory on file system.\n");
> >+	MSG("      but it can be avoided by using this working directory on the file system.\n");
> > 	MSG("      So if you specify this option, the filtering speed may be bit faster.\n");
> >+	MSG("      The directory path may be absolute or relative.\n");
> >+	MSG("      If relative, it is taken to be based at the root filesystem.\n");
> >+	MSG("      It may be an existing directory expressed with the path to the root filesystem as\n");
> >+	MSG("      it is mounted in the crashkernel.\n");
> >+	MSG("      Or it may expressed with '/' as the path to the root filesystem. In that case it will\n");
> >+	MSG("      be automatically adjusted to be relative to the root of the crashkernel.\n");
> >+	MSG("      The root of the crashkernel is determined from the dump name, if present. An assumption\n");
> >+	MSG("      is made that the dump file is to be written to /var/crash/.\n");
> >+	MSG("      If the directory does not exist it will be created, including multiple components.\n");
> > 	MSG("\n");
> > 	MSG("  [--non-mmap]:\n");
> > 	MSG("      Never use mmap(2) to read VMCORE even if it supports mmap(2).\n");

-- 
Cliff Wickman
SGI
cpw at sgi.com
(651)683-7524 vnet 207524
(651)482-9347 home



More information about the kexec mailing list