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

Cliff Wickman cpw at sgi.com
Thu Sep 10 08:27:36 PDT 2015


From: Cliff Wickman <cpw at sgi.com>

This patch enhances the --work-dir feature to make it easier to use.

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 (as currently)
  or allow it to match the 'path' variable in /etc/kdump.conf or the 'KDUMP_SAVEDIR' variable
  in /etc/sysconfig/kdump. In this case it will be automatically adjusted to match how the root
  device is mounted in the crashkernel.
- Make the directory if it does not already exist.  All components of the path are
  made if necessary, similar to mkdir -p.
- Corrects some allocation (off-by-one) errors in the previous version of this patch.

---
 makedumpfile.c |  173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 makedumpfile.h |    3 
 print_info.c   |   16 +++--
 3 files changed, 187 insertions(+), 5 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,175 @@ 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 need the --work-dir path to accurately extract the leading part of
+ * the dump file's path as the path to the root filesystem.
+ * Conventionally --work-dir will be the directory name to which dumps will
+ * be written.  But it could be the absolute, crashkernel-relative path
+ * to a working directory.  In the second case we do not need to set
+ * info-root_dir, and this function should not even be called.
+ */
+void
+set_rootdir()
+{
+	int len1, len2;
+	char *cp1, *cp2, *rootdir, *dumpdir;
+
+	/* allow this function to be called multiple times */
+	if (info->root_dir)
+		return;
+
+	/* without a dump file name we cannot determine the path to root */
+	if (!info->name_dumpfile) {
+		info->root_dir = NULL;
+		return;
+	}
+	if ((int)strlen(info->name_dumpfile) == 0) {
+		info->root_dir = NULL;
+		return;
+	}
+
+	/*
+	 * name_dumpfile might be /kdump/0/var/crash/xyz
+	 * working_dir   might be /var/crash
+	 * so the root path is /kdump/0
+	 */
+	len1 = strlen(info->name_dumpfile);
+	rootdir = malloc(len1 + 2);
+	strcpy(rootdir, info->name_dumpfile);
+	if (*(rootdir + len1 - 1) != '/' )
+		strcat(rootdir, "/");
+	len1 = strlen(rootdir);
+	info->root_dir = malloc(len1);
+
+	len2 = strlen(info->working_dir);
+	dumpdir = malloc(len2 + 2);
+	strcpy(dumpdir, info->working_dir);
+	if (*(dumpdir + len2 - 1) != '/' )
+		strcat(dumpdir, "/");
+	len2 = strlen(dumpdir);
+
+	/* find the dumpdir path within the rootdir path */
+	cp1 = rootdir;
+	cp2 = cp1;
+	while (*cp2 != '\0') {
+		if (!strncmp(cp2, dumpdir, len2)) {
+			len1 = cp2 - cp1;
+			strncpy(info->root_dir, cp1, len1);
+			/* name_dumpfile sometimes contains // */
+			if (*(info->root_dir + len1 - 1) == '/' )
+				*(info->root_dir + len1 - 1) = '\0';
+			if (!isdir(info->root_dir)) {
+				fprintf(stderr,
+				  "Error: root directory %s does not exist\n",
+					info->root_dir);
+				exit(1);
+			}
+			free(rootdir);
+			free(dumpdir);
+			return;
+		}
+		cp2++;
+	}
+	info->root_dir = NULL;
+	free(rootdir);
+	free(dumpdir);
+	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;
+
+	/* we cannot assume makedumpfile's current directory, so make the
+	   work-dir's path absolute */
+	if (strncmp(info->working_dir, "/", 1)) {
+		hold = malloc(strlen(info->working_dir) + 2);
+		strcpy(hold, "/");
+		strcat(hold, info->working_dir);
+		free(hold);
+	}
+
+	/* if a path that is valid in the crashkernel root environment
+	   was specified, no adjust is necessary */
+	if (isdir(info->working_dir))
+		return;
+
+	set_rootdir();
+
+	/* the path does not exist in the crashkernel's root, so it
+	   should be adjusted to be relative to that root path */
+	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, hold);
+		free (hold);
+		fprintf(stderr, "--workdir adjusted to %s\n",
+			info->working_dir);
+	} else {
+		inter_dir = malloc(strlen(info->working_dir) + 1);
+	}
+
+	/* 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},
@@ -10650,6 +10820,9 @@ main(int argc, char *argv[])
 				goto out;
 		}
 
+		if (info->working_dir)
+			adjust_working_dir();
+
 		if (!create_dumpfile())
 			goto out;
 
Index: code/print_info.c
===================================================================
--- code.orig/print_info.c
+++ code/print_info.c
@@ -221,11 +221,19 @@ 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("      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("      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\n");
+	MSG("      consumption but it can be avoided by using this working directory on\n");
+	MSG("      the file system.\n");
 	MSG("      So if you specify this option, the filtering speed may be bit faster.\n");
+	MSG("      It may be an existing directory expressed with the path to the root\n");
+	MSG("      file system as it is mounted in the crashkernel.\n");
+	MSG("      Or, more conventionally, it should match the 'path' variable in\n");
+	MSG("      /etc/kdump.conf or the 'KDUMP_SAVEDIR' variable (directory portion) in\n");
+	MSG("      /etc/sysconfig/kdump. In this case it will be automatically adjusted\n");
+	MSG("      to be relative to the root of the crashkernel.\n");
+	MSG("      The root of the crashkernel is determined using the dump name, if present.\n");
 	MSG("\n");
 	MSG("  [--non-mmap]:\n");
 	MSG("      Never use mmap(2) to read VMCORE even if it supports mmap(2).\n");
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;		/* path to the root filesystem */
 	mdf_pfn_t          num_dumpable;
 	unsigned long      bufsize_cyclic;
 	unsigned long      pfn_cyclic;



More information about the kexec mailing list