xfs
[Top] [All Lists]

[PATCH] Core dump file control

To: Linux XFS List <linux-xfs@xxxxxxxxxxx>
Subject: [PATCH] Core dump file control
From: Michael Sinz <msinz@xxxxxxxxx>
Date: Thu, 14 Feb 2002 11:39:04 -0500
Organization: WorldGate Communications Inc.
Sender: owner-linux-xfs@xxxxxxxxxxx
I have, for a long time, wished that Linux had a way to specify where
core dumps are stored and what the name of the core dump is.  Now that
I have been building large linux clusters with many diskless nodes,
this need has become even more important.  The reason I am sending this
here is that we actually use the XFS 2.4 tree for a lot of our work.
I am also submitting a patch (almost exactly the same) to the main Linux
tree but I thought that those who use large systems (which usually
involves something like XFS) would also be interested.

What I did with this patch is provide a new sysctl that lets you
control the name of the core file.  The this name is actually a format
string such that certain values from the process can be included.

The sysctl is kernel.core_name_format and is a string up to 63 characters
(plus 1 for the null)

The following format options are available in that string:

        %P      The Process ID (current->pid)
        %U      The UID of the process (current->uid)
        %N      The command name of the process (current->comm)
        %H      The nodename of the system (system_utsname.nodename)
        %%      A "%"

For example, in my clusters, I have an NFS R/W mount at /coredumps
that all nodes have access to.  The format string I use is:

        sysctl -w "kernel.core_name_format=/coredumps/%H-%N-%P.core"

This then causes core dumps to be of the format:

        /coredumps/whale.sinz.org-badprogram-13917.core

Only behavior of appending the PID to the "core" name is still
supported with the added logic of only doing so if the PID is
not already part of the name format.  The default name format
is still just "core" to match old behavior.

NOTE - I was tempted to change the default format to be something
like "%N.core" which would at least identify the program that
caused the core file.  However, I can do that as part of my init
process so it is not a issue here.

The attached cvs diff is from the 2.4 tree.

Index: include/linux/sysctl.h
===================================================================
RCS file: /cvs/linux-2.4-xfs/linux/include/linux/sysctl.h,v
retrieving revision 1.45
diff -u -4 -w -w -r1.45 sysctl.h
--- include/linux/sysctl.h      2002/01/11 23:31:51     1.45
+++ include/linux/sysctl.h      2002/02/14 17:30:57
@@ -126,8 +126,9 @@
        KERN_CADPID=54,         /* int: PID of the process to notify on CAD */
 #ifdef CONFIG_KDB
        KERN_KDB=55,            /* int: kdb on/off */
 #endif /* CONFIG_KDB */
+       KERN_CORE_NAME_FORMAT=56, /* string: core file name format string */
 };
 
 
 /* CTL_VM names: */
Index: kernel/sysctl.c
===================================================================
RCS file: /cvs/linux-2.4-xfs/linux/kernel/sysctl.c,v
retrieving revision 1.47
diff -u -4 -w -w -r1.47 sysctl.c
--- kernel/sysctl.c     2002/01/04 03:48:48     1.47
+++ kernel/sysctl.c     2002/02/14 17:30:59
@@ -51,8 +51,9 @@
 extern atomic_t nr_queued_signals;
 extern int max_queued_signals;
 extern int sysrq_enabled;
 extern int core_uses_pid;
+extern char core_name_format [];
 extern int cad_pid;
 
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
@@ -173,8 +174,10 @@
        {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
         0644, NULL, &proc_dointvec},
        {KERN_CORE_USES_PID, "core_uses_pid", &core_uses_pid, sizeof(int),
         0644, NULL, &proc_dointvec},
+       {KERN_CORE_NAME_FORMAT, "core_name_format", core_name_format, 64,
+        0644, NULL, &proc_doutsstring, &sysctl_string},
        {KERN_TAINTED, "tainted", &tainted, sizeof(int),
         0644, NULL, &proc_dointvec},
        {KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t),
         0600, NULL, &proc_dointvec_bset},
Index: fs/exec.c
===================================================================
RCS file: /cvs/linux-2.4-xfs/linux/fs/exec.c,v
retrieving revision 1.50
diff -u -4 -w -w -r1.50 exec.c
--- fs/exec.c   2001/12/23 05:47:19     1.50
+++ fs/exec.c   2002/02/14 17:30:52
@@ -34,8 +34,9 @@
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/spinlock.h>
 #include <linux/personality.h>
+#include <linux/utsname.h>
 #define __NO_VERSION__
 #include <linux/module.h>
 
 #include <asm/uaccess.h>
@@ -46,8 +47,9 @@
 #include <linux/kmod.h>
 #endif
 
 int core_uses_pid;
+char core_name_format[64] = {"core"};
 
 static struct linux_binfmt *formats;
 static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED;
 
@@ -932,15 +934,23 @@
        if (old && old->module)
                __MOD_DEC_USE_COUNT(old->module);
 }
 
+#define MAX_CORE_NAME (160)
 int do_coredump(long signr, struct pt_regs * regs)
 {
        struct linux_binfmt * binfmt;
-       char corename[6+sizeof(current->comm)+10];
+
+       /* The 11 extra are for the support of the old "uses PID option"
+          and such that the PID option does not need some fancy size trick */
+       char corename[MAX_CORE_NAME+1+11];
        struct file * file;
        struct inode * inode;
        int retval = 0;
+       int fmt_i;
+       int name_n;
+       int addPID;
+       char *cname;
 
        lock_kernel();
        binfmt = current->binfmt;
        if (!binfmt || !binfmt->core_dump)
@@ -949,13 +959,93 @@
                goto fail;
        current->mm->dumpable = 0;
        if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
                goto fail;
+
+       /* Set this to true if we are going to add the PID.  If the PID
+          already is added in the format we will end up clearing this.
+          The purpose is to provide for the old behavior of adding the
+          PID to the core file name but to not add it if it already
+          was included via the file name format pattern. */
+       addPID = (core_uses_pid || atomic_read(&current->mm->mm_users) != 1);
+
+       /* Build the core file name as needed from the format string */
+       for (fmt_i=0, name_n=0;
+                name_n < MAX_CORE_NAME && core_name_format[fmt_i];
+                fmt_i++)
+       {
+               switch (core_name_format[fmt_i])
+               {
+               case '%':       /* A format character */
+                       fmt_i++;
+                       switch (core_name_format[fmt_i])
+                       {
+                       case '%': /* The way we get this character */
+                               corename[name_n++] = '%';
+                               break;
+
+                       case 'N': /* Process name */
+                               cname=current->comm;
+
+                               /* Only copy as much as will fit within the 
MAX_CORE_NAME */
+                               while (*cname && (name_n < MAX_CORE_NAME))
+                               {
+                                       if (*cname != '/')
+                                               corename[name_n++] = *cname;
+                                       cname++;
+                               }
+                               break;
+
+                       case 'H': /* Host name */
+                               cname=system_utsname.nodename;
+
+                               /* Only copy as much as will fit within the 
MAX_CORE_NAME */
+                               while (*cname && (name_n < MAX_CORE_NAME))
+                               {
+                                       if (*cname != '/')
+                                               corename[name_n++] = *cname;
+                                       cname++;
+                               }
+                               break;
+
+                       case 'P': /* Process PID */
+                               /* Since we are adding it here, don't append at 
end */
+                               addPID=0;
+
+                               /* We don't need to pre-check that the number 
fits since we
+                                  added a padding of 11 characters to the end 
of the string
+                                  buffer just so that we don't need to do an 
extra check */
+                               name_n += 
sprintf(&corename[name_n],"%d",current->pid);
+                               break;
+
+                       case 'U': /* UID of the process */
+                               /* We don't need to pre-check that the number 
fits since we
+                                  added a padding of 11 characters to the end 
of the string
+                                  buffer just so that we don't need to do an 
extra check */
+                               name_n += 
sprintf(&corename[name_n],"%d",current->uid);
+                               break;
+                       }
+                       break;
+
+               default:        /* Anything else just pass along */
+                       corename[name_n++] = core_name_format[fmt_i];
+               }
+       }
+
+       /* If we still want to append the PID and there is room, do so */
+       /* This is mainly for compatibility */
+       if (addPID && (name_n < MAX_CORE_NAME))
+       {
+               name_n += sprintf(&corename[name_n],".%d",current->pid);
+       }
+
+       /* And null terminate the string */
+       corename[name_n]='\0';
+
+       /* Check that we actually got a name */
+       if (name_n < 1)
+           goto fail;
 
-       memcpy(corename,"core.", 5);
-       corename[4] = '\0';
-       if (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)
-               sprintf(&corename[4], ".%d", current->pid);
        file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW, 0600);
        if (IS_ERR(file))
                goto fail;
        inode = file->f_dentry->d_inode;

-- 
Michael Sinz ---- Worldgate Communications ---- msinz@xxxxxxxxx
A master's secrets are only as good as
        the master's ability to explain them to others.


<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH] Core dump file control, Michael Sinz <=