aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2017-10-25 00:51:00 +0000
committerMark Johnston <markj@FreeBSD.org>2017-10-25 00:51:00 +0000
commit64a16434d8dbd5432e2f1a49007e53a449d43830 (patch)
treee9cdb0a8780646580c9a0d35fd94332c6a2443ad /sys
parent7b79d6d61ac82b21e2acc396a4ea66d0e92c79d9 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/null/null.c2
-rw-r--r--sys/geom/geom_dev.c9
-rw-r--r--sys/kern/kern_gzio.c29
-rw-r--r--sys/kern/kern_shutdown.c297
-rw-r--r--sys/sys/conf.h5
-rw-r--r--sys/sys/disk.h1
-rw-r--r--sys/sys/gzio.h1
-rw-r--r--sys/sys/kerneldump.h11
8 files changed, 299 insertions, 56 deletions
diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c
index d946da6208ff..22654a251de4 100644
--- a/sys/dev/null/null.c
+++ b/sys/dev/null/null.c
@@ -114,7 +114,7 @@ null_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused,
case DIOCSKERNELDUMP_FREEBSD11:
#endif
case DIOCSKERNELDUMP:
- error = set_dumper(NULL, NULL, td, 0, NULL, 0, NULL);
+ error = set_dumper(NULL, NULL, td, 0, 0, NULL, 0, NULL);
break;
case FIONBIO:
break;
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 03a404682b1c..202c9f7dc0a4 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -138,7 +138,7 @@ g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda,
int error, len;
if (dev == NULL || kda == NULL)
- return (set_dumper(NULL, NULL, td, 0, NULL, 0, NULL));
+ return (set_dumper(NULL, NULL, td, 0, 0, NULL, 0, NULL));
cp = dev->si_drv2;
len = sizeof(kd);
@@ -148,8 +148,9 @@ g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda,
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_compression,
+ kda->kda_encryption, kda->kda_key, kda->kda_encryptedkeysize,
+ kda->kda_encryptedkey);
if (error == 0)
dev->si_flags |= SI_DUMPDEV;
@@ -832,7 +833,7 @@ g_dev_orphan(struct g_consumer *cp)
/* 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, 0, 0, NULL, 0, NULL);
/* Destroy the struct cdev *so we get no more requests */
destroy_dev_sched_cb(dev, g_dev_callback, cp);
diff --git a/sys/kern/kern_gzio.c b/sys/kern/kern_gzio.c
index cee21f0655b1..f659b9bb7d7a 100644
--- a/sys/kern/kern_gzio.c
+++ b/sys/kern/kern_gzio.c
@@ -60,7 +60,6 @@ struct gzio_stream *
gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
{
struct gzio_stream *s;
- uint8_t *hdr;
int error;
if (bufsz < KERN_GZ_HDRLEN)
@@ -72,7 +71,6 @@ gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
s->gz_bufsz = bufsz;
s->gz_buffer = gz_alloc(NULL, 1, s->gz_bufsz);
s->gz_mode = mode;
- s->gz_crc = ~0U;
s->gz_cb = cb;
s->gz_arg = arg;
@@ -87,6 +85,26 @@ gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
if (error != 0)
goto fail;
+ gzio_reset(s);
+
+ return (s);
+
+fail:
+ gz_free(NULL, s->gz_buffer);
+ gz_free(NULL, s);
+ return (NULL);
+}
+
+void
+gzio_reset(struct gzio_stream *s)
+{
+ uint8_t *hdr;
+
+ (void)deflateReset(&s->gz_stream);
+
+ s->gz_off = 0;
+ s->gz_crc = ~0U;
+
s->gz_stream.avail_out = s->gz_bufsz;
s->gz_stream.next_out = s->gz_buffer;
@@ -99,13 +117,6 @@ gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
hdr[9] = OS_CODE;
s->gz_stream.next_out += KERN_GZ_HDRLEN;
s->gz_stream.avail_out -= KERN_GZ_HDRLEN;
-
- return (s);
-
-fail:
- gz_free(NULL, s->gz_buffer);
- gz_free(NULL, s);
- return (NULL);
}
int
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 36c275809add..c73df509249e 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#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 @@ __FBSDID("$FreeBSD$");
#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,24 @@ struct kerneldumpcrypto {
};
#endif
+#ifdef GZIO
+struct kerneldumpgz {
+ struct gzio_stream *kdgz_stream;
+ uint8_t *kdgz_buf;
+ size_t kdgz_resid;
+};
+
+static struct kerneldumpgz *kerneldumpgz_create(struct dumperinfo *di,
+ uint8_t compression);
+static void kerneldumpgz_destroy(struct dumperinfo *di);
+static int kerneldumpgz_write_cb(void *cb, size_t len, off_t off, void *arg);
+
+static int kerneldump_gzlevel = 6;
+SYSCTL_INT(_kern, OID_AUTO, kerneldump_gzlevel, CTLFLAG_RWTUN,
+ &kerneldump_gzlevel, 0,
+ "Kernel crash dump gzip 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.
@@ -857,6 +877,9 @@ static char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)];
SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
dumpdevname, 0, "Device for kernel dumps");
+static int _dump_append(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,
@@ -947,11 +970,45 @@ kerneldumpcrypto_dumpkeysize(const struct kerneldumpcrypto *kdc)
}
#endif /* EKCD */
+#ifdef GZIO
+static struct kerneldumpgz *
+kerneldumpgz_create(struct dumperinfo *di, uint8_t compression)
+{
+ struct kerneldumpgz *kdgz;
+
+ if (compression != KERNELDUMP_COMP_GZIP)
+ return (NULL);
+ kdgz = malloc(sizeof(*kdgz), M_DUMPER, M_WAITOK | M_ZERO);
+ kdgz->kdgz_stream = gzio_init(kerneldumpgz_write_cb, GZIO_DEFLATE,
+ di->maxiosize, kerneldump_gzlevel, di);
+ if (kdgz->kdgz_stream == NULL) {
+ free(kdgz, M_DUMPER);
+ return (NULL);
+ }
+ kdgz->kdgz_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP);
+ return (kdgz);
+}
+
+static void
+kerneldumpgz_destroy(struct dumperinfo *di)
+{
+ struct kerneldumpgz *kdgz;
+
+ kdgz = di->kdgz;
+ if (kdgz == NULL)
+ return;
+ gzio_fini(kdgz->kdgz_stream);
+ explicit_bzero(kdgz->kdgz_buf, di->maxiosize);
+ free(kdgz->kdgz_buf, M_DUMPER);
+ free(kdgz, M_DUMPER);
+}
+#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)
+ uint8_t compression, uint8_t encryption, const uint8_t *key,
+ uint32_t encryptedkeysize, const uint8_t *encryptedkey)
{
size_t wantcopy;
int error;
@@ -969,6 +1026,7 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
dumper = *di;
dumper.blockbuf = NULL;
dumper.kdc = NULL;
+ dumper.kdgz = NULL;
if (encryption != KERNELDUMP_ENC_NONE) {
#ifdef EKCD
@@ -987,7 +1045,28 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
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 (compression != KERNELDUMP_COMP_NONE) {
+#ifdef GZIO
+ /*
+ * We currently can't support simultaneous encryption and
+ * compression.
+ */
+ if (encryption != KERNELDUMP_ENC_NONE) {
+ error = EOPNOTSUPP;
+ goto cleanup;
+ }
+ dumper.kdgz = kerneldumpgz_create(&dumper, compression);
+ if (dumper.kdgz == NULL) {
+ error = EINVAL;
+ goto cleanup;
+ }
+#else
+ error = EOPNOTSUPP;
+ goto cleanup;
+#endif
}
dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
@@ -1000,6 +1079,11 @@ cleanup:
free(dumper.kdc, M_EKCD);
}
#endif
+
+#ifdef GZIO
+ kerneldumpgz_destroy(&dumper);
+#endif
+
if (dumper.blockbuf != NULL) {
explicit_bzero(dumper.blockbuf, dumper.blocksize);
free(dumper.blockbuf, M_DUMPER);
@@ -1090,22 +1174,57 @@ dump_encrypted_write(struct dumperinfo *di, void *virtual,
}
static int
-dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset)
+dump_write_key(struct dumperinfo *di, off_t offset)
{
struct kerneldumpcrypto *kdc;
kdc = di->kdc;
if (kdc == NULL)
return (0);
-
- return (dump_write(di, kdc->kdc_dumpkey, physical, offset,
+ return (dump_write(di, kdc->kdc_dumpkey, 0, offset,
kdc->kdc_dumpkeysize));
}
#endif /* EKCD */
+#ifdef GZIO
+static int
+kerneldumpgz_write_cb(void *base, size_t length, off_t offset, void *arg)
+{
+ struct dumperinfo *di;
+ size_t resid, 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_append(di, base, 0, rlength);
+ if (error != 0)
+ return (error);
+ }
+ resid = length - rlength;
+ memmove(di->blockbuf, (uint8_t *)base + rlength, resid);
+ di->kdgz->kdgz_resid = resid;
+ return (EAGAIN);
+ }
+ return (_dump_append(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)
+ off_t offset)
{
void *buf;
size_t hdrsz;
@@ -1122,7 +1241,7 @@ dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
memcpy(buf, kdh, hdrsz);
}
- return (dump_write(di, buf, physical, offset, di->blocksize));
+ return (dump_write(di, buf, 0, offset, di->blocksize));
}
/*
@@ -1132,19 +1251,30 @@ dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
#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.
+ *
+ * We set things up so that the dump ends before the last sector of the dump
+ * device, at which the trailing header is written.
+ *
+ * +-----------+------+-----+----------------------------+------+
+ * | | lhdr | key | ... kernel dump ... | thdr |
+ * +-----------+------+-----+----------------------------+------+
+ * 1 blk opt <------- dump extent --------> 1 blk
+ *
+ * Dumps written using dump_append() start at the beginning of the extent.
+ * Uncompressed dumps will use the entire extent, but compressed dumps typically
+ * will not. The true length of the dump is recorded in the leading and trailing
+ * headers once the dump has been completed.
*/
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);
@@ -1152,30 +1282,36 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
keysize = 0;
#endif
- dumpsize = dtoh64(kdh->dumplength) + 2 * di->blocksize + keysize;
- if (di->mediasize < SIZEOF_METADATA + dumpsize)
- return (E2BIG);
-
- di->dumpoff = di->mediaoffset + di->mediasize - dumpsize;
-
- error = dump_write_header(di, kdh, 0, di->dumpoff);
- if (error != 0)
- return (error);
- di->dumpoff += di->blocksize;
-
-#ifdef EKCD
- error = dump_write_key(di, 0, di->dumpoff);
- if (error != 0)
- return (error);
- di->dumpoff += keysize;
+ dumpextent = dtoh64(kdh->dumpextent);
+ if (di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
+ keysize) {
+#ifdef GZIO
+ if (di->kdgz != 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_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 (E2BIG);
+ }
+
+ /* The offset at which to begin writing the dump. */
+ di->dumpoff = di->mediaoffset + di->mediasize - di->blocksize -
+ dumpextent;
return (0);
}
-/* Write to the dump device at the current dump offset. */
-int
-dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical,
+static int
+_dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical,
size_t length)
{
int error;
@@ -1192,7 +1328,33 @@ dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical,
return (error);
}
-/* Perform a raw write to the dump device at the specified offset. */
+/*
+ * 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_append(struct dumperinfo *di, void *virtual, vm_offset_t physical,
+ size_t length)
+{
+#ifdef GZIO
+ void *buf;
+
+ if (di->kdgz != NULL) {
+ /* Bounce through a buffer to avoid gzip CRC errors. */
+ if (length > di->maxiosize)
+ return (EINVAL);
+ buf = di->kdgz->kdgz_buf;
+ memmove(buf, virtual, length);
+ return (gzio_write(di->kdgz->kdgz_stream, buf, length));
+ }
+#endif
+ return (_dump_append(di, virtual, physical, length));
+}
+
+/*
+ * Write to the dump device at the specified offset.
+ */
int
dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
off_t offset, size_t length)
@@ -1206,15 +1368,71 @@ dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
}
/*
- * Write the trailing kernel dump header and signal to the lower layers that the
- * dump has completed.
+ * 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, di->dumpoff);
+ extent = dtoh64(kdh->dumpextent);
+
+#ifdef EKCD
+ keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
+#else
+ keysize = 0;
+#endif
+
+#ifdef GZIO
+ if (di->kdgz != NULL) {
+ error = gzio_flush(di->kdgz->kdgz_stream);
+ if (error == EAGAIN) {
+ /* We have residual data in di->blockbuf. */
+ error = dump_write(di, di->blockbuf, 0, di->dumpoff,
+ di->blocksize);
+ di->dumpoff += di->kdgz->kdgz_resid;
+ di->kdgz->kdgz_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(di->dumpoff -
+ (di->mediaoffset + di->mediasize - di->blocksize - extent));
+ kdh->parity = 0;
+ kdh->parity = kerneldump_parity(kdh);
+
+ gzio_reset(di->kdgz->kdgz_stream);
+ }
+#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,
+ di->mediaoffset + di->mediasize - 2 * di->blocksize - extent -
+ keysize);
+ if (error != 0)
+ return (error);
+
+#ifdef EKCD
+ error = dump_write_key(di,
+ di->mediaoffset + di->mediasize - di->blocksize - extent - keysize);
+ if (error != 0)
+ return (error);
+#endif
+
+ error = dump_write_header(di, kdh,
+ di->mediaoffset + di->mediasize - di->blocksize);
if (error != 0)
return (error);
@@ -1234,6 +1452,7 @@ dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh,
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(di->kdc));
@@ -1247,6 +1466,10 @@ dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh,
kdh->versionstring[dstsize - 2] = '\n';
if (panicstr != NULL)
strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
+#ifdef GZIO
+ if (di->kdgz != NULL)
+ kdh->compression = KERNELDUMP_COMP_GZIP;
+#endif
kdh->parity = kerneldump_parity(kdh);
}
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index 4c33ec34a9b6..90e2afe20529 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -338,14 +338,15 @@ struct dumperinfo {
void *blockbuf; /* Buffer for padding shorter dump blocks */
off_t dumpoff; /* Offset of ongoing kernel dump. */
struct kerneldumpcrypto *kdc; /* Kernel dump crypto. */
+ struct kerneldumpgz *kdgz; /* Kernel dump compression. */
};
extern int dumping; /* system is dumping */
int doadump(boolean_t);
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);
+ uint8_t compression, uint8_t encryption, const uint8_t *key,
+ uint32_t encryptedkeysize, const uint8_t *encryptedkey);
int dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh);
int dump_append(struct dumperinfo *, void *, vm_offset_t, size_t);
diff --git a/sys/sys/disk.h b/sys/sys/disk.h
index 5c65eb177889..4ab0b09e12cd 100644
--- a/sys/sys/disk.h
+++ b/sys/sys/disk.h
@@ -143,6 +143,7 @@ struct diocgattr_arg {
struct diocskerneldump_arg {
uint8_t kda_enable;
+ uint8_t kda_compression;
uint8_t kda_encryption;
uint8_t kda_key[KERNELDUMP_KEY_MAX_SIZE];
uint32_t kda_encryptedkeysize;
diff --git a/sys/sys/gzio.h b/sys/sys/gzio.h
index c61c2818f2e9..524d80238fac 100644
--- a/sys/sys/gzio.h
+++ b/sys/sys/gzio.h
@@ -40,6 +40,7 @@ typedef int (*gzio_cb)(void *, size_t, off_t, void *);
struct gzio_stream;
struct gzio_stream *gzio_init(gzio_cb cb, enum gzio_mode, size_t, int, void *);
+void gzio_reset(struct gzio_stream *);
int gzio_write(struct gzio_stream *, void *, u_int);
int gzio_flush(struct gzio_stream *);
void gzio_fini(struct gzio_stream *);
diff --git a/sys/sys/kerneldump.h b/sys/sys/kerneldump.h
index afd762923a57..864640ae5ff1 100644
--- a/sys/sys/kerneldump.h
+++ b/sys/sys/kerneldump.h
@@ -55,6 +55,9 @@
#define htod64(x) (x)
#endif
+#define KERNELDUMP_COMP_NONE 0
+#define KERNELDUMP_COMP_GZIP 1
+
#define KERNELDUMP_ENC_NONE 0
#define KERNELDUMP_ENC_AES_256_CBC 1
@@ -75,8 +78,8 @@ struct kerneldumpheader {
#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
@@ -87,12 +90,14 @@ struct kerneldumpheader {
#define KERNELDUMP_RISCV_VERSION 1
#define KERNELDUMP_SPARC64_VERSION 1
uint64_t dumplength; /* excl headers */
+ uint64_t dumpextent;
uint64_t dumptime;
uint32_t dumpkeysize;
uint32_t blocksize;
+ uint8_t compression;
char hostname[64];
char versionstring[192];
- char panicstring[188];
+ char panicstring[179];
uint32_t parity;
};