Work much harder at obtaining a correct device node. If what devname(3)
returns doesn't exist, or doesn't match the desired device, fall back to scanning /dev for a matching node, and as a last resort, if that fails, try to create the node ourselves as /dev/dump. Add comments to several variables and functions. Clean up syslog(3) usage; use %m instead of strerror(3). Other minor cleanup.
This commit is contained in:
parent
a0951dd59e
commit
c74e16f917
@ -55,7 +55,7 @@ static const char rcsid[] =
|
|||||||
#include <vm/vm_param.h>
|
#include <vm/vm_param.h>
|
||||||
#include <vm/pmap.h>
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
@ -106,15 +106,15 @@ off_t dumplo; /* where dump starts on dumpdev */
|
|||||||
int dumpmag; /* magic number in dump */
|
int dumpmag; /* magic number in dump */
|
||||||
int dumpsize; /* amount of memory dumped */
|
int dumpsize; /* amount of memory dumped */
|
||||||
|
|
||||||
char *kernel;
|
char *kernel; /* user-specified kernel */
|
||||||
char *savedir; /* directory to save dumps in */
|
char *savedir; /* directory to save dumps in */
|
||||||
char *ddname; /* name of dump device */
|
char ddname[MAXPATHLEN]; /* name of dump device */
|
||||||
dev_t dumpdev; /* dump device */
|
dev_t dumpdev; /* dump device */
|
||||||
int dumpfd; /* read/write descriptor on char dev */
|
int dumpfd; /* read/write descriptor on char dev */
|
||||||
time_t now; /* current date */
|
time_t now; /* current date */
|
||||||
char panic_mesg[1024];
|
char panic_mesg[1024]; /* panic message */
|
||||||
int panicstr;
|
int panicstr; /* flag: dump was caused by panic */
|
||||||
char vers[1024];
|
char vers[1024]; /* version of kernel that crashed */
|
||||||
|
|
||||||
int clear, compress, force, verbose; /* flags */
|
int clear, compress, force, verbose; /* flags */
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ void clear_dump __P((void));
|
|||||||
void DumpRead __P((int fd, void *bp, int size, off_t off, int flag));
|
void DumpRead __P((int fd, void *bp, int size, off_t off, int flag));
|
||||||
void DumpWrite __P((int fd, void *bp, int size, off_t off, int flag));
|
void DumpWrite __P((int fd, void *bp, int size, off_t off, int flag));
|
||||||
int dump_exists __P((void));
|
int dump_exists __P((void));
|
||||||
char *find_dev __P((dev_t));
|
void find_dev __P((dev_t));
|
||||||
int get_crashtime __P((void));
|
int get_crashtime __P((void));
|
||||||
void get_dumpsize __P((void));
|
void get_dumpsize __P((void));
|
||||||
void kmem_setup __P((void));
|
void kmem_setup __P((void));
|
||||||
@ -226,8 +226,7 @@ kmem_setup()
|
|||||||
* the same!)
|
* the same!)
|
||||||
*/
|
*/
|
||||||
if ((nlist(getbootfile(), current_nl)) == -1)
|
if ((nlist(getbootfile(), current_nl)) == -1)
|
||||||
syslog(LOG_ERR, "%s: nlist: %s", getbootfile(),
|
syslog(LOG_ERR, "%s: nlist: %m", getbootfile());
|
||||||
strerror(errno));
|
|
||||||
for (i = 0; cursyms[i] != -1; i++)
|
for (i = 0; cursyms[i] != -1; i++)
|
||||||
if (current_nl[cursyms[i]].n_value == 0) {
|
if (current_nl[cursyms[i]].n_value == 0) {
|
||||||
syslog(LOG_ERR, "%s: %s not in namelist",
|
syslog(LOG_ERR, "%s: %s not in namelist",
|
||||||
@ -237,7 +236,7 @@ kmem_setup()
|
|||||||
|
|
||||||
dump_sys = kernel ? kernel : getbootfile();
|
dump_sys = kernel ? kernel : getbootfile();
|
||||||
if ((nlist(dump_sys, dump_nl)) == -1)
|
if ((nlist(dump_sys, dump_nl)) == -1)
|
||||||
syslog(LOG_ERR, "%s: nlist: %s", dump_sys, strerror(errno));
|
syslog(LOG_ERR, "%s: nlist: %m", dump_sys);
|
||||||
for (i = 0; dumpsyms[i] != -1; i++)
|
for (i = 0; dumpsyms[i] != -1; i++)
|
||||||
if (dump_nl[dumpsyms[i]].n_value == 0) {
|
if (dump_nl[dumpsyms[i]].n_value == 0) {
|
||||||
syslog(LOG_ERR, "%s: %s not in namelist",
|
syslog(LOG_ERR, "%s: %s not in namelist",
|
||||||
@ -266,7 +265,7 @@ kmem_setup()
|
|||||||
(long long)dumplo, kdumplo, DEV_BSIZE);
|
(long long)dumplo, kdumplo, DEV_BSIZE);
|
||||||
Lseek(kmem, (off_t)current_nl[X_DUMPMAG].n_value, L_SET);
|
Lseek(kmem, (off_t)current_nl[X_DUMPMAG].n_value, L_SET);
|
||||||
(void)Read(kmem, &dumpmag, sizeof(dumpmag));
|
(void)Read(kmem, &dumpmag, sizeof(dumpmag));
|
||||||
ddname = find_dev(dumpdev);
|
find_dev(dumpdev);
|
||||||
dumpfd = Open(ddname, O_RDWR);
|
dumpfd = Open(ddname, O_RDWR);
|
||||||
fp = fdopen(kmem, "r");
|
fp = fdopen(kmem, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
@ -304,17 +303,24 @@ check_kmem()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the magic number in the dump header.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
clear_dump()
|
clear_dump()
|
||||||
{
|
{
|
||||||
long newdumplo;
|
int newdumpmag;
|
||||||
|
|
||||||
newdumplo = 0;
|
newdumpmag = 0;
|
||||||
DumpWrite(dumpfd, &newdumplo, sizeof(newdumplo),
|
DumpWrite(dumpfd, &newdumpmag, sizeof(newdumpmag),
|
||||||
(off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
|
(off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
|
||||||
close(dumpfd);
|
close(dumpfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a dump exists by looking for a magic number in the dump
|
||||||
|
* header.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
dump_exists()
|
dump_exists()
|
||||||
{
|
{
|
||||||
@ -334,6 +340,9 @@ dump_exists()
|
|||||||
|
|
||||||
char buf[1024 * 1024];
|
char buf[1024 * 1024];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the core dump.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
save_core()
|
save_core()
|
||||||
{
|
{
|
||||||
@ -351,7 +360,7 @@ save_core()
|
|||||||
goto err1;
|
goto err1;
|
||||||
if (fgets(buf, sizeof(buf), fp) == NULL) {
|
if (fgets(buf, sizeof(buf), fp) == NULL) {
|
||||||
if (ferror(fp))
|
if (ferror(fp))
|
||||||
err1: syslog(LOG_WARNING, "%s: %s", path, strerror(errno));
|
err1: syslog(LOG_WARNING, "%s: %m", path);
|
||||||
bounds = 0;
|
bounds = 0;
|
||||||
} else
|
} else
|
||||||
bounds = atoi(buf);
|
bounds = atoi(buf);
|
||||||
@ -373,7 +382,7 @@ err1: syslog(LOG_WARNING, "%s: %s", path, strerror(errno));
|
|||||||
else
|
else
|
||||||
fp = fopen(path, "w");
|
fp = fopen(path, "w");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
syslog(LOG_ERR, "%s: %s", path, strerror(errno));
|
syslog(LOG_ERR, "%s: %m", path);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
(void)umask(oumask);
|
(void)umask(oumask);
|
||||||
@ -398,8 +407,7 @@ err1: syslog(LOG_WARNING, "%s: %s", path, strerror(errno));
|
|||||||
}
|
}
|
||||||
nw = fwrite(buf, 1, nr, fp);
|
nw = fwrite(buf, 1, nr, fp);
|
||||||
if (nw != nr) {
|
if (nw != nr) {
|
||||||
syslog(LOG_ERR, "%s: %s",
|
syslog(LOG_ERR, "%s: %m", path);
|
||||||
path, strerror(nw == 0 ? EIO : errno));
|
|
||||||
err2: syslog(LOG_WARNING,
|
err2: syslog(LOG_WARNING,
|
||||||
"WARNING: vmcore may be incomplete");
|
"WARNING: vmcore may be incomplete");
|
||||||
(void)printf("\n");
|
(void)printf("\n");
|
||||||
@ -418,7 +426,7 @@ err2: syslog(LOG_WARNING,
|
|||||||
else
|
else
|
||||||
fp = fopen(path, "w");
|
fp = fopen(path, "w");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
syslog(LOG_ERR, "%s: %s", path, strerror(errno));
|
syslog(LOG_ERR, "%s: %m", path);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
syslog(LOG_NOTICE, "writing %skernel to %s",
|
syslog(LOG_NOTICE, "writing %skernel to %s",
|
||||||
@ -426,16 +434,14 @@ err2: syslog(LOG_WARNING,
|
|||||||
while ((nr = read(ifd, buf, sizeof(buf))) > 0) {
|
while ((nr = read(ifd, buf, sizeof(buf))) > 0) {
|
||||||
nw = fwrite(buf, 1, nr, fp);
|
nw = fwrite(buf, 1, nr, fp);
|
||||||
if (nw != nr) {
|
if (nw != nr) {
|
||||||
syslog(LOG_ERR, "%s: %s",
|
syslog(LOG_ERR, "%s: %m", path);
|
||||||
path, strerror(nw == 0 ? EIO : errno));
|
|
||||||
syslog(LOG_WARNING,
|
syslog(LOG_WARNING,
|
||||||
"WARNING: kernel may be incomplete");
|
"WARNING: kernel may be incomplete");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nr < 0) {
|
if (nr < 0) {
|
||||||
syslog(LOG_ERR, "%s: %s",
|
syslog(LOG_ERR, "%s: %m", kernel ? kernel : getbootfile());
|
||||||
kernel ? kernel : getbootfile(), strerror(errno));
|
|
||||||
syslog(LOG_WARNING,
|
syslog(LOG_WARNING,
|
||||||
"WARNING: kernel may be incomplete");
|
"WARNING: kernel may be incomplete");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -444,22 +450,67 @@ err2: syslog(LOG_WARNING,
|
|||||||
close(ifd);
|
close(ifd);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
/*
|
||||||
|
* Verify that the specified device node exists and matches the
|
||||||
|
* specified device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
verify_dev(name, dev)
|
||||||
|
char *name;
|
||||||
|
register dev_t dev;
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (lstat(name, &sb) == -1)
|
||||||
|
return (-1);
|
||||||
|
if (!S_ISCHR(sb.st_mode) || sb.st_rdev != dev)
|
||||||
|
return (-1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the dump device.
|
||||||
|
*
|
||||||
|
* 1) try devname(3); see if it returns something sensible
|
||||||
|
* 2) scan /dev for the desired node
|
||||||
|
* 3) as a last resort, try to create the node we need
|
||||||
|
*/
|
||||||
|
void
|
||||||
find_dev(dev)
|
find_dev(dev)
|
||||||
register dev_t dev;
|
register dev_t dev;
|
||||||
{
|
{
|
||||||
char *dn;
|
struct dirent *ent;
|
||||||
|
char *dn, *dnp;
|
||||||
|
DIR *d;
|
||||||
|
|
||||||
|
strcpy(ddname, _PATH_DEV);
|
||||||
|
dnp = ddname + sizeof _PATH_DEV - 1;
|
||||||
if ((dn = devname(dev, S_IFCHR)) != NULL) {
|
if ((dn = devname(dev, S_IFCHR)) != NULL) {
|
||||||
if (asprintf(&dn, "/dev/%s", dn) != -1)
|
strcpy(dnp, dn);
|
||||||
return dn;
|
if (verify_dev(ddname, dev) == 0)
|
||||||
syslog(LOG_ERR, "insufficient memory");
|
return;
|
||||||
} else {
|
|
||||||
syslog(LOG_ERR, "can't find device %d/%d", major(dev), minor(dev));
|
|
||||||
}
|
}
|
||||||
|
if ((d = opendir(_PATH_DEV)) != NULL) {
|
||||||
|
while ((ent = readdir(d))) {
|
||||||
|
strcpy(dnp, ent->d_name);
|
||||||
|
if (verify_dev(ddname, dev) == 0) {
|
||||||
|
closedir(d);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
strcpy(dnp, "dump");
|
||||||
|
if (mknod(ddname, S_IFCHR|S_IRUSR|S_IWUSR, dev) == 0)
|
||||||
|
return;
|
||||||
|
syslog(LOG_ERR, "can't find device %d/%#x", major(dev), minor(dev));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the date and time of the crash from the dump header, and
|
||||||
|
* make sure it looks sane (within one week of current date and time).
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
get_crashtime()
|
get_crashtime()
|
||||||
{
|
{
|
||||||
@ -481,6 +532,9 @@ get_crashtime()
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the size of the dump from the dump header.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
get_dumpsize()
|
get_dumpsize()
|
||||||
{
|
{
|
||||||
@ -490,6 +544,10 @@ get_dumpsize()
|
|||||||
dumpsize *= getpagesize();
|
dumpsize *= getpagesize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that sufficient space is available on the disk that holds the
|
||||||
|
* save directory.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
check_space()
|
check_space()
|
||||||
{
|
{
|
||||||
@ -658,7 +716,7 @@ Write(fd, bp, size)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
if ((n = write(fd, bp, size)) < size) {
|
if ((n = write(fd, bp, size)) < size) {
|
||||||
syslog(LOG_ERR, "write: %s", strerror(n == -1 ? errno : EIO));
|
syslog(LOG_ERR, "write: %m");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user