summaryrefslogtreecommitdiffstats
path: root/sbin/savecore/savecore.c
diff options
context:
space:
mode:
authorcem <cem@FreeBSD.org>2016-04-15 17:45:12 +0000
committercem <cem@FreeBSD.org>2016-04-15 17:45:12 +0000
commit98188ed5c2caae40b8e4ca0485baa690f5d10a78 (patch)
tree0b0043fac6329303bacfbbf1d228fc0ded072146 /sbin/savecore/savecore.c
parent12232f84636cebecfa250541cfbf09b07fe2f520 (diff)
downloadFreeBSD-src-98188ed5c2caae40b8e4ca0485baa690f5d10a78.zip
FreeBSD-src-98188ed5c2caae40b8e4ca0485baa690f5d10a78.tar.gz
Add 4Kn kernel dump support
(And 4Kn minidump support, but only for amd64.) Make sure all I/O to the dump device is of the native sector size. To that end, we keep a native sector sized buffer associated with dump devices (di->blockbuf) and use it to pad smaller objects as needed (e.g. kerneldumpheader). Add dump_write_pad() as a convenience API to dump smaller objects with zero padding. (Rather than pull in NPM leftpad, we wrote our own.) Savecore(1) has been updated to deal with these dumps. The format for 512-byte sector dumps should remain backwards compatible. Minidumps for other architectures are left as an exercise for the reader. PR: 194279 Submitted by: ambrisko@ Reviewed by: cem (earlier version), rpokala Tested by: rpokala (4Kn/512 except 512 fulldump), cem (512 fulldump) Relnotes: yes Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D5848
Diffstat (limited to 'sbin/savecore/savecore.c')
-rw-r--r--sbin/savecore/savecore.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c
index 7809c58..63f4ef2 100644
--- a/sbin/savecore/savecore.c
+++ b/sbin/savecore/savecore.c
@@ -436,7 +436,7 @@ DoFile(const char *savedir, const char *device)
{
xo_handle_t *xostdout, *xoinfo;
static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX];
- static char *buf = NULL;
+ static char *buf = NULL, *temp = NULL;
struct kerneldumpheader kdhf, kdhl;
off_t mediasize, dumpsize, firsthd, lasthd;
FILE *info, *fp;
@@ -490,14 +490,29 @@ DoFile(const char *savedir, const char *device)
printf("sectorsize = %u\n", sectorsize);
}
+ if (sectorsize < sizeof(kdhl)) {
+ syslog(LOG_ERR,
+ "Sector size is less the kernel dump header %zu",
+ sizeof(kdhl));
+ goto closefd;
+ }
+
lasthd = mediasize - sectorsize;
+ if (temp == NULL) {
+ temp = malloc(sectorsize);
+ if (temp == NULL) {
+ syslog(LOG_ERR, "%m");
+ return;
+ }
+ }
if (lseek(fd, lasthd, SEEK_SET) != lasthd ||
- read(fd, &kdhl, sizeof(kdhl)) != sizeof(kdhl)) {
+ read(fd, temp, sectorsize) != sectorsize) {
syslog(LOG_ERR,
"error reading last dump header at offset %lld in %s: %m",
(long long)lasthd, device);
goto closefd;
}
+ memcpy(&kdhl, temp, sizeof(kdhl));
istextdump = 0;
if (strncmp(kdhl.magic, TEXTDUMPMAGIC, sizeof kdhl) == 0) {
if (verbose)
@@ -567,15 +582,16 @@ DoFile(const char *savedir, const char *device)
goto closefd;
}
dumpsize = dtoh64(kdhl.dumplength);
- firsthd = lasthd - dumpsize - sizeof kdhf;
+ firsthd = lasthd - dumpsize - sectorsize;
if (lseek(fd, firsthd, SEEK_SET) != firsthd ||
- read(fd, &kdhf, sizeof(kdhf)) != sizeof(kdhf)) {
+ read(fd, temp, sectorsize) != sectorsize) {
syslog(LOG_ERR,
"error reading first dump header at offset %lld in %s: %m",
(long long)firsthd, device);
nerr++;
goto closefd;
}
+ memcpy(&kdhf, temp, sizeof(kdhf));
if (verbose >= 2) {
printf("First dump headers:\n");
@@ -586,7 +602,7 @@ DoFile(const char *savedir, const char *device)
printf("\n");
}
- if (memcmp(&kdhl, &kdhf, sizeof kdhl)) {
+ if (memcmp(&kdhl, &kdhf, sizeof(kdhl))) {
syslog(LOG_ERR,
"first and last dump headers disagree on %s", device);
nerr++;
@@ -603,7 +619,7 @@ DoFile(const char *savedir, const char *device)
exit(0);
}
- if (kdhl.panicstring[0])
+ if (kdhl.panicstring[0] != '\0')
syslog(LOG_ALERT, "reboot after panic: %*s",
(int)sizeof(kdhl.panicstring), kdhl.panicstring);
else
@@ -724,9 +740,10 @@ nuke:
if (!keep) {
if (verbose)
printf("clearing dump header\n");
- memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof kdhl.magic);
+ memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof(kdhl.magic));
+ memcpy(temp, &kdhl, sizeof(kdhl));
if (lseek(fd, lasthd, SEEK_SET) != lasthd ||
- write(fd, &kdhl, sizeof(kdhl)) != sizeof(kdhl))
+ write(fd, temp, sectorsize) != sectorsize)
syslog(LOG_ERR,
"error while clearing the dump header: %m");
}
OpenPOWER on IntegriCloud