Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152041608
D11723.id31151.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D11723.id31151.diff
View Options
Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf
+++ etc/defaults/rc.conf
@@ -598,6 +598,8 @@
dumpdir="/var/crash" # Directory where crash dumps are to be stored
dumppubkey="" # Public key for encrypted kernel crash dumps.
# See dumpon(8) for more details.
+dumpcompress="NO" # Configure the kernel to compress crash dumps before
+ # writing them to the dump device.
savecore_enable="YES" # Extract core from dump devices if any
savecore_flags="-m 10" # Used if dumpdev is enabled above, and present.
# By default, only the 10 most recent kernel dumps
Index: etc/rc.d/dumpon
===================================================================
--- etc/rc.d/dumpon
+++ etc/rc.d/dumpon
@@ -16,11 +16,15 @@
dumpon_try()
{
+ local flags
+
if [ -n "${dumppubkey}" ]; then
- /sbin/dumpon -k "${dumppubkey}" "${1}"
- else
- /sbin/dumpon "${1}"
+ flags="${flags} -k ${dumppubkey}"
+ fi
+ if checkyesno dumpcompress; then
+ flags="${flags} -c"
fi
+ /sbin/dumpon ${flags} "${1}"
if [ $? -eq 0 ]; then
# Make a symlink in devfs for savecore
ln -fs "${1}" /dev/dumpdev
Index: sbin/dumpon/dumpon.8
===================================================================
--- sbin/dumpon/dumpon.8
+++ sbin/dumpon/dumpon.8
@@ -37,6 +37,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl v
+.Op Fl c
.Op Fl k Ar public_key_file
.Ar special_file
.Nm
@@ -85,6 +86,15 @@
variable.
.Pp
The
+.Op c
+option configures the kernel to write a compressed dump to the dump device.
+This reduces the amount of space required for the dump.
+When compression is enabled, the
+.Nm
+utility will not verify that the dump device is sufficiently large for a full
+dump.
+.Pp
+The
.Op Fl k Ar public_key_file
flag causes
.Nm
Index: sbin/dumpon/dumpon.c
===================================================================
--- sbin/dumpon/dumpon.c
+++ sbin/dumpon/dumpon.c
@@ -71,7 +71,7 @@
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n",
- "usage: dumpon [-v] [-k public_key_file] special_file",
+ "usage: dumpon [-v] [-c] [-k public_key_file] special_file",
" dumpon [-v] off",
" dumpon [-v] -l");
exit(EX_USAGE);
@@ -190,12 +190,16 @@
int ch;
int i, fd;
int do_listdumpdev = 0;
- bool enable;
+ bool compress, enable;
+ compress = false;
pubkeyfile = NULL;
- while ((ch = getopt(argc, argv, "k:lv")) != -1)
+ while ((ch = getopt(argc, argv, "ck:lv")) != -1)
switch((char)ch) {
+ case 'c':
+ compress = true;
+ break;
case 'k':
pubkeyfile = optarg;
break;
@@ -247,9 +251,11 @@
fd = open(dumpdev, O_RDONLY);
if (fd < 0)
err(EX_OSFILE, "%s", dumpdev);
- check_size(fd, dumpdev);
- bzero(&kda, sizeof(kda));
+ if (!compress)
+ check_size(fd, dumpdev);
+
+ bzero(&kda, sizeof(kda));
kda.kda_enable = 0;
i = ioctl(fd, DIOCSKERNELDUMP, &kda);
explicit_bzero(&kda, sizeof(kda));
@@ -260,6 +266,7 @@
#endif
kda.kda_enable = 1;
+ kda.kda_compress = compress;
i = ioctl(fd, DIOCSKERNELDUMP, &kda);
explicit_bzero(kda.kda_encryptedkey, kda.kda_encryptedkeysize);
free(kda.kda_encryptedkey);
Index: sbin/savecore/savecore.c
===================================================================
--- sbin/savecore/savecore.c
+++ sbin/savecore/savecore.c
@@ -121,6 +121,9 @@
(long long)dumplen);
xo_emit_h(xo, "{P: }{Lwc:Blocksize}{:blocksize/%d}\n",
dtoh32(h->blocksize));
+ xo_emit_h(xo, "{P: }{Lwc:Compression}{:compression/%s}\n",
+ h->compression == KERNELDUMP_COMPRESSION_DEFLATE ?
+ "DEFLATE" : "none");
t = dtoh64(h->dumptime);
xo_emit_h(xo, "{P: }{Lwc:Dumptime}{:dumptime/%s}", ctime(&t));
@@ -357,7 +360,7 @@
#define BLOCKMASK (~(BLOCKSIZE-1))
static int
-DoRegularFile(int fd, bool isencrypted, off_t dumpsize, char *buf,
+DoRegularFile(int fd, off_t dumpsize, u_int sectorsize, bool sparse, char *buf,
const char *device, const char *filename, FILE *fp)
{
int he, hs, nr, nw, wl;
@@ -370,8 +373,8 @@
wl = BUFFERSIZE;
if (wl > dumpsize)
wl = dumpsize;
- nr = read(fd, buf, wl);
- if (nr != wl) {
+ nr = read(fd, buf, roundup(wl, sectorsize));
+ if (nr != (int)roundup(wl, sectorsize)) {
if (nr == 0)
syslog(LOG_WARNING,
"WARNING: EOF on dump device");
@@ -380,7 +383,7 @@
nerr++;
return (-1);
}
- if (compress || isencrypted) {
+ if (!sparse) {
nw = fwrite(buf, 1, wl, fp);
} else {
for (nw = 0; nw < nr; nw = he) {
@@ -506,15 +509,14 @@
char *temp = NULL;
struct kerneldumpheader kdhf, kdhl;
uint8_t *dumpkey;
- off_t mediasize, dumpsize, firsthd, lasthd;
+ off_t mediasize, dumpextent, dumplength, firsthd, lasthd;
FILE *info, *fp;
mode_t oumask;
int fd, fdinfo, error;
int bounds, status;
u_int sectorsize, xostyle;
- int istextdump;
uint32_t dumpkeysize;
- bool isencrypted, ret;
+ bool iscompressed, isencrypted, istextdump, ret;
bounds = getbounds();
dumpkey = NULL;
@@ -582,12 +584,12 @@
goto closefd;
}
memcpy(&kdhl, temp, sizeof(kdhl));
- istextdump = 0;
+ iscompressed = istextdump = false;
if (compare_magic(&kdhl, TEXTDUMPMAGIC)) {
if (verbose)
printf("textdump magic on last dump header on %s\n",
device);
- istextdump = 1;
+ istextdump = true;
if (dtoh32(kdhl.version) != KERNELDUMP_TEXT_VERSION) {
syslog(LOG_ERR,
"unknown version (%d) in last dump header on %s",
@@ -607,6 +609,11 @@
if (force == 0)
goto closefd;
}
+ if (kdhl.compression == KERNELDUMP_COMPRESSION_DEFLATE) {
+ if (compress && verbose)
+ printf("dump is already compressed\n");
+ iscompressed = true;
+ }
} else {
if (verbose)
printf("magic mismatch on last dump header on %s\n",
@@ -619,8 +626,7 @@
if (compare_magic(&kdhl, KERNELDUMPMAGIC_CLEARED)) {
if (verbose)
printf("forcing magic on %s\n", device);
- memcpy(kdhl.magic, KERNELDUMPMAGIC,
- sizeof kdhl.magic);
+ memcpy(kdhl.magic, KERNELDUMPMAGIC, sizeof(kdhl.magic));
} else {
syslog(LOG_ERR, "unable to force dump - bad magic");
goto closefd;
@@ -648,9 +654,10 @@
if (force == 0)
goto closefd;
}
- dumpsize = dtoh64(kdhl.dumplength);
+ dumpextent = dtoh64(kdhl.dumpextent);
+ dumplength = dtoh64(kdhl.dumplength);
dumpkeysize = dtoh32(kdhl.dumpkeysize);
- firsthd = lasthd - dumpsize - sectorsize - dumpkeysize;
+ firsthd = lasthd - dumpextent - sectorsize - dumpkeysize;
if (lseek(fd, firsthd, SEEK_SET) != firsthd ||
read(fd, temp, sectorsize) != (ssize_t)sectorsize) {
syslog(LOG_ERR,
@@ -696,7 +703,7 @@
if (verbose)
printf("Checking for available free space\n");
- if (!check_space(savedir, dumpsize, bounds)) {
+ if (!check_space(savedir, dumplength, bounds)) {
nerr++;
goto closefd;
}
@@ -724,6 +731,10 @@
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds);
fp = zopen(corename, "w");
+ } else if (iscompressed && !isencrypted) {
+ /* We compress before encrypting. */
+ snprintf(corename, sizeof(corename), "vmcore.%d.gz", bounds);
+ fp = fopen(corename, "w");
} else {
snprintf(corename, sizeof(corename), "%s.%d",
istextdump ? "textdump.tar" :
@@ -792,11 +803,12 @@
savedir, corename);
if (istextdump) {
- if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device,
+ if (DoTextdumpFile(fd, dumplength, lasthd, buf, device,
corename, fp) < 0)
goto closeall;
} else {
- if (DoRegularFile(fd, isencrypted, dumpsize, buf, device,
+ if (DoRegularFile(fd, dumplength, sectorsize,
+ !(compress || iscompressed || isencrypted), buf, device,
corename, fp) < 0) {
goto closeall;
}
@@ -822,7 +834,7 @@
"key.last");
}
}
- if (compress) {
+ if (compress || (iscompressed && !isencrypted)) {
snprintf(linkname, sizeof(linkname), "%s.last.gz",
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"));
Index: share/man/man5/rc.conf.5
===================================================================
--- share/man/man5/rc.conf.5
+++ share/man/man5/rc.conf.5
@@ -3409,6 +3409,16 @@
See
.Xr dumpon 8
for more details.
+.It Va dumpcompress
+Set to
+.Dq Li YES
+to enable compression of crash dumps before they are written to the
+dump device.
+This allows larger crash dumps to be saved to the dump device, and
+speeds up recovery of crash dumps following a reboot.
+This feature depends on the
+.Dv GZIO
+kernel option.
.It Va savecore_enable
.Pq Vt bool
If set to
Index: sys/dev/null/null.c
===================================================================
--- sys/dev/null/null.c
+++ sys/dev/null/null.c
@@ -114,7 +114,7 @@
case DIOCSKERNELDUMP_FREEBSD11:
#endif
case DIOCSKERNELDUMP:
- error = set_dumper(NULL, NULL, td, 0, NULL, 0, NULL);
+ error = set_dumper(NULL, NULL, td, false, 0, NULL, 0, NULL);
break;
case FIONBIO:
break;
Index: sys/geom/geom_dev.c
===================================================================
--- sys/geom/geom_dev.c
+++ sys/geom/geom_dev.c
@@ -138,7 +138,7 @@
int error, len;
if (dev == NULL || kda == NULL)
- return (set_dumper(NULL, NULL, td, 0, NULL, 0, NULL));
+ return (set_dumper(NULL, NULL, td, false, 0, NULL, 0, NULL));
cp = dev->si_drv2;
len = sizeof(kd);
@@ -148,8 +148,9 @@
if (error != 0)
return (error);
- error = set_dumper(&kd.di, devtoname(dev), td, kda->kda_encryption,
- kda->kda_key, kda->kda_encryptedkeysize, kda->kda_encryptedkey);
+ error = set_dumper(&kd.di, devtoname(dev), td, kda->kda_compress,
+ kda->kda_encryption, kda->kda_key, kda->kda_encryptedkeysize,
+ kda->kda_encryptedkey);
if (error == 0)
dev->si_flags |= SI_DUMPDEV;
@@ -817,7 +818,8 @@
/* Reset any dump-area set on this device */
if (dev->si_flags & SI_DUMPDEV)
- (void)set_dumper(NULL, NULL, curthread, 0, NULL, 0, NULL);
+ (void)set_dumper(NULL, NULL, curthread, false, 0, NULL, 0,
+ NULL);
/* Destroy the struct cdev *so we get no more requests */
destroy_dev_sched_cb(dev, g_dev_callback, cp);
Index: sys/kern/kern_shutdown.c
===================================================================
--- sys/kern/kern_shutdown.c
+++ sys/kern/kern_shutdown.c
@@ -39,6 +39,7 @@
#include "opt_ddb.h"
#include "opt_ekcd.h"
+#include "opt_gzio.h"
#include "opt_kdb.h"
#include "opt_panic.h"
#include "opt_sched.h"
@@ -52,6 +53,7 @@
#include <sys/cons.h>
#include <sys/eventhandler.h>
#include <sys/filedesc.h>
+#include <sys/gzio.h>
#include <sys/jail.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -162,6 +164,20 @@
};
#endif
+#ifdef GZIO
+static struct gzio_stream *dumpgzs;
+static uint8_t *gzbuffer;
+
+static int kerneldump_gz_configure(struct dumperinfo *di);
+static void kerneldump_gz_disable(void);
+static int kerneldump_gz_write_cb(void *cb, size_t len, off_t off, void *arg);
+
+static int kerneldump_gz_level = 6;
+SYSCTL_INT(_kern, OID_AUTO, kerneldump_gz_level, CTLFLAG_RW,
+ &kerneldump_gz_level, 0,
+ "Kernel crash dump compression level");
+#endif /* GZIO */
+
/*
* Variable panicstr contains argument to first call to panic; used as flag
* to indicate that the kernel has already called panic.
@@ -858,6 +874,9 @@
SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
dumpdevname, 0, "Device for kernel dumps");
+static int _dump_write(struct dumperinfo *di, void *virtual,
+ vm_offset_t physical, size_t length);
+
#ifdef EKCD
static struct kerneldumpcrypto *
kerneldumpcrypto_create(size_t blocksize, uint8_t encryption,
@@ -948,11 +967,37 @@
}
#endif /* EKCD */
+#ifdef GZIO
+static int
+kerneldump_gz_configure(struct dumperinfo *di)
+{
+
+ dumpgzs = gzio_init(kerneldump_gz_write_cb, GZIO_DEFLATE, di->maxiosize,
+ kerneldump_gz_level, di);
+ if (dumpgzs == NULL)
+ return (EINVAL);
+ gzbuffer = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP);
+ return (0);
+}
+
+static void
+kerneldump_gz_disable(void)
+{
+
+ if (dumpgzs != NULL) {
+ gzio_fini(dumpgzs);
+ dumpgzs = NULL;
+ }
+ free(gzbuffer, M_DUMPER);
+ gzbuffer = NULL;
+}
+#endif /* GZIO */
+
/* Registration of dumpers */
int
set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
- uint8_t encryption, const uint8_t *key, uint32_t encryptedkeysize,
- const uint8_t *encryptedkey)
+ bool compress, uint8_t encryption, const uint8_t *key,
+ uint32_t encryptedkeysize, const uint8_t *encryptedkey)
{
size_t wantcopy;
int error;
@@ -988,7 +1033,26 @@
wantcopy = strlcpy(dumpdevname, devname, sizeof(dumpdevname));
if (wantcopy >= sizeof(dumpdevname)) {
printf("set_dumper: device name truncated from '%s' -> '%s'\n",
- devname, dumpdevname);
+ devname, dumpdevname);
+ }
+
+ if (compress) {
+#ifdef GZIO
+ /*
+ * We currently can't support simultaneous encryption and
+ * compression.
+ */
+ if (encryption != KERNELDUMP_ENC_NONE) {
+ error = EOPNOTSUPP;
+ goto cleanup;
+ }
+ error = kerneldump_gz_configure(&dumper);
+ if (error != 0)
+ goto cleanup;
+#else
+ error = EOPNOTSUPP;
+ goto cleanup;
+#endif
}
dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
@@ -1001,6 +1065,11 @@
free(dumper.kdc, M_EKCD);
}
#endif
+
+#ifdef GZIO
+ kerneldump_gz_disable();
+#endif
+
if (dumper.blockbuf != NULL) {
explicit_bzero(dumper.blockbuf, dumper.blocksize);
free(dumper.blockbuf, M_DUMPER);
@@ -1104,6 +1173,41 @@
}
#endif /* EKCD */
+#ifdef GZIO
+static int
+kerneldump_gz_write_cb(void *base, size_t length, off_t offset, void *arg)
+{
+ struct dumperinfo *di;
+ size_t rlength;
+ int error;
+
+ di = arg;
+
+ if (length % di->blocksize != 0) {
+ /*
+ * This must be the final write after flushing the compression
+ * stream. Write as many full blocks as possible and stash the
+ * residual data in the dumper's block buffer. It will be
+ * padded and written in dump_finish().
+ */
+ rlength = rounddown(length, di->blocksize);
+ if (rlength != 0) {
+ error = _dump_write(di, base, 0, rlength);
+ if (error != 0)
+ return (error);
+ }
+ di->resid = length - rlength;
+ memmove(di->blockbuf, (uint8_t *)base + rlength, di->resid);
+ return (EAGAIN);
+ }
+ return (_dump_write(di, base, 0, length));
+}
+#endif /* GZIO */
+
+/*
+ * Write a kerneldumpheader at the specified offset. The header structure is 512
+ * bytes in size, but we must pad to the device sector size.
+ */
static int
dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
vm_offset_t physical, off_t offset)
@@ -1133,19 +1237,17 @@
#define SIZEOF_METADATA (64 * 1024)
/*
- * Do some preliminary setup for a kernel dump: verify that we have enough space
- * on the dump device, write the leading header, and optionally write the crypto
- * key.
+ * Do some preliminary setup for a kernel dump: initialize state for encryption,
+ * if requested, and make sure that we have enough space on the dump device.
*/
int
dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
{
- uint64_t dumpsize;
+ uint64_t dumpextent;
uint32_t keysize;
- int error;
#ifdef EKCD
- error = kerneldumpcrypto_init(di->kdc);
+ int error = kerneldumpcrypto_init(di->kdc);
if (error != 0)
return (error);
keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
@@ -1153,33 +1255,40 @@
keysize = 0;
#endif
- dumpsize = dtoh64(kdh->dumplength) + 2 * di->blocksize + keysize;
- if (di->mediasize < SIZEOF_METADATA + dumpsize)
- return (ENOSPC);
+ dumpextent = dtoh64(kdh->dumpextent);
+ if (di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
+ keysize) {
+#ifdef GZIO
+ if (dumpgzs != NULL) {
+ /*
+ * We don't yet know how much space the compressed dump
+ * will occupy, so try to use the whole swap partition
+ * (minus the first 64KB) in the hope that the
+ * compressed dump will fit. If that doesn't turn out to
+ * be enouch, the bounds checking in dump_raw_write()
+ * will catch us and cause the dump to fail.
+ */
+ dumpextent = di->mediasize - SIZEOF_METADATA -
+ 2 * di->blocksize - keysize;
+ kdh->dumpextent = htod64(dumpextent);
+ } else
+#endif
+ return (ENOSPC);
+ }
- dumpoff = di->mediaoffset + di->mediasize - dumpsize;
+ /*
+ * Set the initial offset at which to begin writing the dump.
+ * This excludes the leading header, and the (optional) key.
+ */
+ dumpoff = di->mediaoffset + di->mediasize - dumpextent - di->blocksize;
- error = dump_write_header(di, kdh, 0, dumpoff);
- if (error != 0)
- return (error);
- dumpoff += di->blocksize;
-
-#ifdef EKCD
- error = dump_write_key(di, 0, dumpoff);
- if (error != 0)
- return (error);
- dumpoff += keysize;
-#endif
+ di->resid = 0;
return (0);
}
-/*
- * Write the trailing kernel dump header and signal to the lower layers that the
- * dump has completed.
- */
-int
-dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
+static int
+_dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
size_t length)
{
int error;
@@ -1196,6 +1305,31 @@
return (error);
}
+/*
+ * Write to the dump device starting at dumpoff. When compression is enabled,
+ * writes to the device will be performed using a callback that gets invoked
+ * when the compression stream's output buffer is full.
+ */
+int
+dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
+ size_t length)
+{
+
+#ifdef GZIO
+ if (dumpgzs != NULL) {
+ /* Bounce through a buffer to avoid gzip CRC errors. */
+ if (length > di->maxiosize)
+ return (EINVAL);
+ memmove(gzbuffer, virtual, length);
+ return (gzio_write(dumpgzs, gzbuffer, length));
+ }
+#endif
+ return (_dump_write(di, virtual, physical, length));
+}
+
+/*
+ * Write to the dump device at the specified offset.
+ */
int
dump_raw_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
off_t offset, size_t length)
@@ -1209,12 +1343,70 @@
return (di->dumper(di->priv, virtual, physical, offset, length));
}
+/*
+ * Perform kernel dump finalization: flush the compression stream, if necessary,
+ * write the leading and trailing kernel dump headers now that we know the true
+ * length of the dump, and optionally write the encryption key following the
+ * leading header.
+ */
int
dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh)
{
+ uint64_t extent;
+ uint32_t keysize;
int error;
- error = dump_write_header(di, kdh, 0, dumpoff);
+ extent = dtoh64(kdh->dumpextent);
+
+#ifdef EKCD
+ keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
+#else
+ keysize = 0;
+#endif
+
+#ifdef GZIO
+ if (dumpgzs != NULL) {
+ error = gzio_flush(dumpgzs);
+ if (error == EAGAIN) {
+ /* We have residual data in di->blockbuf. */
+ error = dump_raw_write(di, di->blockbuf, 0, dumpoff,
+ di->blocksize);
+ dumpoff += di->resid;
+ di->resid = 0;
+ }
+ if (error != 0)
+ return (error);
+
+ /*
+ * We now know the size of the compressed dump, so update the
+ * header accordingly and recompute parity.
+ */
+ kdh->dumplength = htod64(dumpoff -
+ (di->mediaoffset + di->mediasize - extent - di->blocksize));
+ kdh->parity = 0;
+ kdh->parity = kerneldump_parity(kdh);
+ }
+#endif
+
+ /*
+ * Write kerneldump headers at the beginning and end of the dump extent.
+ * Write the key after the leading header.
+ */
+ error = dump_write_header(di, kdh, 0,
+ di->mediaoffset + di->mediasize - 2 * di->blocksize - extent -
+ keysize);
+ if (error != 0)
+ return (error);
+
+#ifdef EKCD
+ error = dump_write_key(di, 0,
+ di->mediaoffset + di->mediasize - di->blocksize - extent - keysize);
+ if (error != 0)
+ return (error);
+#endif
+
+ error = dump_write_header(di, kdh, 0,
+ di->mediaoffset + di->mediasize - di->blocksize);
if (error != 0)
return (error);
@@ -1234,6 +1426,7 @@
kdh->version = htod32(KERNELDUMPVERSION);
kdh->architectureversion = htod32(archver);
kdh->dumplength = htod64(dumplen);
+ kdh->dumpextent = kdh->dumplength;
kdh->dumptime = htod64(time_second);
#ifdef EKCD
kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(dumper.kdc));
@@ -1247,6 +1440,10 @@
kdh->versionstring[dstsize - 2] = '\n';
if (panicstr != NULL)
strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
+#ifdef GZIO
+ if (dumpgzs != NULL)
+ kdh->compression = KERNELDUMP_COMPRESSION_DEFLATE;
+#endif
kdh->parity = kerneldump_parity(kdh);
}
Index: sys/sys/conf.h
===================================================================
--- sys/sys/conf.h
+++ sys/sys/conf.h
@@ -336,12 +336,13 @@
off_t mediaoffset; /* Initial offset in bytes. */
off_t mediasize; /* Space available in bytes. */
void *blockbuf; /* Buffer for padding shorter dump blocks */
+ size_t resid; /* Residual data from compression stream. */
struct kerneldumpcrypto *kdc; /* Kernel dump crypto. */
};
int set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
- uint8_t encrypt, const uint8_t *key, uint32_t encryptedkeysize,
- const uint8_t *encryptedkey);
+ bool compress, uint8_t encrypt, const uint8_t *key,
+ uint32_t encryptedkeysize, const uint8_t *encryptedkey);
int dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh);
int dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh);
int dump_write(struct dumperinfo *, void *, vm_offset_t, size_t);
Index: sys/sys/disk.h
===================================================================
--- sys/sys/disk.h
+++ sys/sys/disk.h
@@ -142,6 +142,7 @@
struct diocskerneldump_arg {
uint8_t kda_enable;
+ uint8_t kda_compress;
uint8_t kda_encryption;
uint8_t kda_key[KERNELDUMP_KEY_MAX_SIZE];
uint32_t kda_encryptedkeysize;
Index: sys/sys/kerneldump.h
===================================================================
--- sys/sys/kerneldump.h
+++ sys/sys/kerneldump.h
@@ -75,8 +75,8 @@
#define KERNELDUMPMAGIC_CLEARED "Cleared Kernel Dump"
char architecture[12];
uint32_t version;
-#define KERNELDUMPVERSION 2
-#define KERNELDUMP_TEXT_VERSION 2
+#define KERNELDUMPVERSION 3
+#define KERNELDUMP_TEXT_VERSION 3
uint32_t architectureversion;
#define KERNELDUMP_AARCH64_VERSION 1
#define KERNELDUMP_AMD64_VERSION 2
@@ -86,13 +86,17 @@
#define KERNELDUMP_POWERPC_VERSION 1
#define KERNELDUMP_RISCV_VERSION 1
#define KERNELDUMP_SPARC64_VERSION 1
- uint64_t dumplength; /* excl headers */
+ uint64_t dumplength; /* excl headers; compressed */
+ uint64_t dumpextent; /* space between headers */
uint64_t dumptime;
uint32_t dumpkeysize;
uint32_t blocksize;
+ uint8_t compression;
+#define KERNELDUMP_COMPRESSION_UNCOMPRESSED 0
+#define KERNELDUMP_COMPRESSION_DEFLATE 1
char hostname[64];
char versionstring[192];
- char panicstring[188];
+ char panicstring[179];
uint32_t parity;
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 13, 7:33 AM (3 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31367238
Default Alt Text
D11723.id31151.diff (22 KB)
Attached To
Mode
D11723: Add support for compressed kernel dumps.
Attached
Detach File
Event Timeline
Log In to Comment