svn commit: r327707 - in head: share/man/man5 sys/conf sys/ddb sys/kern sys/sys
Mark Johnston
markj at FreeBSD.org
Mon Jan 8 21:27:43 UTC 2018
Author: markj
Date: Mon Jan 8 21:27:41 2018
New Revision: 327707
URL: https://svnweb.freebsd.org/changeset/base/327707
Log:
Generalize the gzio API.
We currently use a set of subroutines in kern_gzio.c to perform
compression of user and kernel core dumps. In the interest of adding
support for other compression algorithms (zstd) in this role without
complicating the API consumers, add a simple compressor API which can be
used to select an algorithm.
Also change the (non-default) GZIO kernel option to not enable
compressed user cores by default. It's not clear that such a default
would be desirable with support for multiple algorithms implemented,
and it's inconsistent in that it isn't applied to kernel dumps.
Reviewed by: cem
Differential Revision: https://reviews.freebsd.org/D13632
Added:
head/sys/kern/subr_compressor.c
- copied, changed from r327706, head/sys/kern/kern_gzio.c
head/sys/sys/compressor.h
- copied, changed from r327706, head/sys/sys/gzio.h
Deleted:
head/sys/kern/kern_gzio.c
head/sys/sys/gzio.h
Modified:
head/share/man/man5/core.5
head/sys/conf/files
head/sys/ddb/db_textdump.c
head/sys/kern/imgact_elf.c
head/sys/kern/kern_shutdown.c
head/sys/kern/kern_sig.c
head/sys/sys/conf.h
head/sys/sys/imgact.h
Modified: head/share/man/man5/core.5
==============================================================================
--- head/share/man/man5/core.5 Mon Jan 8 20:14:16 2018 (r327706)
+++ head/share/man/man5/core.5 Mon Jan 8 21:27:41 2018 (r327707)
@@ -28,7 +28,7 @@
.\" @(#)core.5 8.3 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd October 5, 2015
+.Dd January 8, 2018
.Dt CORE 5
.Os
.Sh NAME
@@ -67,8 +67,8 @@ generating it).
.Pp
The following format specifiers may be used in the
.Va kern.corefile
-sysctl to insert additional information into the resulting core file
-name:
+sysctl to insert additional information into the resulting core
+filename:
.Bl -tag -width "1234567890" -compact -offset "12345"
.It Em \&%H
Machine hostname.
@@ -108,17 +108,17 @@ is included in the kernel configuration file:
GZIO
.El
.Pp
-When the GZIO option is included, the following sysctls control whether core
-files will be compressed:
-.Bl -tag -width "kern.compress_user_cores_gzlevel" -compact -offset "12345"
-.It Em kern.compress_user_cores_gzlevel
-Gzip compression level.
-Defaults to 6.
+The following sysctl control core file compression:
+.Bl -tag -width "kern.compress_user_cores_level" -compact -offset "12345"
.It Em kern.compress_user_cores
-Actually compress user cores.
-Compressed core files will have a suffix of
+Enable compression of user cores.
+A value of 1 configures gzip compression.
+gzip-compressed core files will have a suffix of
.Ql .gz
-appended to them.
+appended to their filenames.
+.It Em kern.compress_user_cores_level
+Compression level.
+Defaults to 6.
.El
.Sh NOTES
Corefiles are written with open file descriptor information as an ELF note.
@@ -153,6 +153,7 @@ command can be used:
.Dl sysctl kern.corefile=/var/coredumps/\&%U/\&%N.core
.Sh SEE ALSO
.Xr gdb 1 ,
+.Xr gzip 1 ,
.Xr kgdb 1 ,
.Xr setrlimit 2 ,
.Xr sigaction 2 ,
Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Mon Jan 8 20:14:16 2018 (r327706)
+++ head/sys/conf/files Mon Jan 8 21:27:41 2018 (r327707)
@@ -3767,7 +3767,6 @@ kern/kern_exit.c standard
kern/kern_fail.c standard
kern/kern_ffclock.c standard
kern/kern_fork.c standard
-kern/kern_gzio.c optional gzio
kern/kern_hhook.c standard
kern/kern_idle.c standard
kern/kern_intr.c standard
@@ -3843,6 +3842,7 @@ kern/subr_bus_dma.c standard
kern/subr_bufring.c standard
kern/subr_capability.c standard
kern/subr_clock.c standard
+kern/subr_compressor.c standard
kern/subr_counter.c standard
kern/subr_devstat.c standard
kern/subr_disk.c standard
Modified: head/sys/ddb/db_textdump.c
==============================================================================
--- head/sys/ddb/db_textdump.c Mon Jan 8 20:14:16 2018 (r327706)
+++ head/sys/ddb/db_textdump.c Mon Jan 8 21:27:41 2018 (r327707)
@@ -454,8 +454,8 @@ textdump_dumpsys(struct dumperinfo *di)
/*
* Disable EKCD because we don't provide encrypted textdumps.
*/
- kdc = di->kdc;
- di->kdc = NULL;
+ kdc = di->kdcrypto;
+ di->kdcrypto = NULL;
/*
* Position the start of the dump so that we'll write the kernel dump
@@ -512,7 +512,7 @@ textdump_dumpsys(struct dumperinfo *di)
/*
* Restore EKCD status.
*/
- di->kdc = kdc;
+ di->kdcrypto = kdc;
}
/*-
Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c Mon Jan 8 20:14:16 2018 (r327706)
+++ head/sys/kern/imgact_elf.c Mon Jan 8 21:27:41 2018 (r327707)
@@ -36,13 +36,12 @@ __FBSDID("$FreeBSD$");
#include "opt_capsicum.h"
#include "opt_compat.h"
-#include "opt_gzio.h"
#include <sys/param.h>
#include <sys/capsicum.h>
+#include <sys/compressor.h>
#include <sys/exec.h>
#include <sys/fcntl.h>
-#include <sys/gzio.h>
#include <sys/imgact.h>
#include <sys/imgact_elf.h>
#include <sys/jail.h>
@@ -1185,9 +1184,12 @@ struct coredump_params {
struct ucred *file_cred;
struct thread *td;
struct vnode *vp;
- struct gzio_stream *gzs;
+ struct compressor *comp;
};
+extern int compress_user_cores;
+extern int compress_user_cores_level;
+
static void cb_put_phdr(vm_map_entry_t, void *);
static void cb_size_segment(vm_map_entry_t, void *);
static int core_write(struct coredump_params *, const void *, size_t, off_t,
@@ -1219,9 +1221,6 @@ static void note_procstat_rlimit(void *, struct sbuf *
static void note_procstat_umask(void *, struct sbuf *, size_t *);
static void note_procstat_vmmap(void *, struct sbuf *, size_t *);
-#ifdef GZIO
-extern int compress_user_cores_gzlevel;
-
/*
* Write out a core segment to the compression stream.
*/
@@ -1241,7 +1240,7 @@ compress_chunk(struct coredump_params *p, char *base,
error = copyin(base, buf, chunk_len);
if (error != 0)
bzero(buf, chunk_len);
- error = gzio_write(p->gzs, buf, chunk_len);
+ error = compressor_write(p->comp, buf, chunk_len);
if (error != 0)
break;
base += chunk_len;
@@ -1251,13 +1250,12 @@ compress_chunk(struct coredump_params *p, char *base,
}
static int
-core_gz_write(void *base, size_t len, off_t offset, void *arg)
+core_compressed_write(void *base, size_t len, off_t offset, void *arg)
{
return (core_write((struct coredump_params *)arg, base, len, offset,
UIO_SYSSPACE));
}
-#endif /* GZIO */
static int
core_write(struct coredump_params *p, const void *base, size_t len,
@@ -1275,10 +1273,9 @@ core_output(void *base, size_t len, off_t offset, stru
{
int error;
-#ifdef GZIO
- if (p->gzs != NULL)
+ if (p->comp != NULL)
return (compress_chunk(p, base, tmpbuf, len));
-#endif
+
/*
* EFAULT is a non-fatal error that we can get, for example,
* if the segment is backed by a file but extends beyond its
@@ -1323,11 +1320,9 @@ sbuf_drain_core_output(void *arg, const char *data, in
locked = PROC_LOCKED(p->td->td_proc);
if (locked)
PROC_UNLOCK(p->td->td_proc);
-#ifdef GZIO
- if (p->gzs != NULL)
- error = gzio_write(p->gzs, __DECONST(char *, data), len);
+ if (p->comp != NULL)
+ error = compressor_write(p->comp, __DECONST(char *, data), len);
else
-#endif
error = core_write(p, __DECONST(void *, data), len, p->offset,
UIO_SYSSPACE);
if (locked)
@@ -1362,11 +1357,7 @@ __elfN(coredump)(struct thread *td, struct vnode *vp,
struct note_info *ninfo;
void *hdr, *tmpbuf;
size_t hdrsize, notesz, coresize;
-#ifdef GZIO
- boolean_t compress;
- compress = (flags & IMGACT_CORE_COMPRESS) != 0;
-#endif
hdr = NULL;
tmpbuf = NULL;
TAILQ_INIT(¬elst);
@@ -1391,7 +1382,7 @@ __elfN(coredump)(struct thread *td, struct vnode *vp,
params.file_cred = NOCRED;
params.td = td;
params.vp = vp;
- params.gzs = NULL;
+ params.comp = NULL;
#ifdef RACCT
if (racct_enable) {
@@ -1409,18 +1400,17 @@ __elfN(coredump)(struct thread *td, struct vnode *vp,
goto done;
}
-#ifdef GZIO
/* Create a compression stream if necessary. */
- if (compress) {
- params.gzs = gzio_init(core_gz_write, GZIO_DEFLATE,
- CORE_BUF_SIZE, compress_user_cores_gzlevel, ¶ms);
- if (params.gzs == NULL) {
+ if (compress_user_cores != 0) {
+ params.comp = compressor_init(core_compressed_write,
+ compress_user_cores, CORE_BUF_SIZE,
+ compress_user_cores_level, ¶ms);
+ if (params.comp == NULL) {
error = EFAULT;
goto done;
}
tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO);
}
-#endif
/*
* Allocate memory for building the header, fill it up,
@@ -1446,10 +1436,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp,
offset += php->p_filesz;
php++;
}
-#ifdef GZIO
- if (error == 0 && compress)
- error = gzio_flush(params.gzs);
-#endif
+ if (error == 0 && params.comp != NULL)
+ error = compressor_flush(params.comp);
}
if (error) {
log(LOG_WARNING,
@@ -1458,13 +1446,9 @@ __elfN(coredump)(struct thread *td, struct vnode *vp,
}
done:
-#ifdef GZIO
- if (compress) {
- free(tmpbuf, M_TEMP);
- if (params.gzs != NULL)
- gzio_fini(params.gzs);
- }
-#endif
+ free(tmpbuf, M_TEMP);
+ if (params.comp != NULL)
+ compressor_fini(params.comp);
while ((ninfo = TAILQ_FIRST(¬elst)) != NULL) {
TAILQ_REMOVE(¬elst, ninfo, link);
free(ninfo, M_TEMP);
Modified: head/sys/kern/kern_shutdown.c
==============================================================================
--- head/sys/kern/kern_shutdown.c Mon Jan 8 20:14:16 2018 (r327706)
+++ head/sys/kern/kern_shutdown.c Mon Jan 8 21:27:41 2018 (r327707)
@@ -41,7 +41,6 @@ __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,10 +51,10 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
+#include <sys/compressor.h>
#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>
@@ -174,23 +173,21 @@ struct kerneldumpcrypto {
};
#endif
-#ifdef GZIO
-struct kerneldumpgz {
- struct gzio_stream *kdgz_stream;
- uint8_t *kdgz_buf;
- size_t kdgz_resid;
+struct kerneldumpcomp {
+ struct compressor *kdc_stream;
+ uint8_t *kdc_buf;
+ size_t kdc_resid;
};
-static struct kerneldumpgz *kerneldumpgz_create(struct dumperinfo *di,
+static struct kerneldumpcomp *kerneldumpcomp_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 void kerneldumpcomp_destroy(struct dumperinfo *di);
+static int kerneldumpcomp_write_cb(void *base, 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 */
+ "Kernel crash dump compression level");
/*
* Variable panicstr contains argument to first call to panic; used as flag
@@ -986,39 +983,37 @@ kerneldumpcrypto_dumpkeysize(const struct kerneldumpcr
}
#endif /* EKCD */
-#ifdef GZIO
-static struct kerneldumpgz *
-kerneldumpgz_create(struct dumperinfo *di, uint8_t compression)
+static struct kerneldumpcomp *
+kerneldumpcomp_create(struct dumperinfo *di, uint8_t compression)
{
- struct kerneldumpgz *kdgz;
+ struct kerneldumpcomp *kdcomp;
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);
+ kdcomp = malloc(sizeof(*kdcomp), M_DUMPER, M_WAITOK | M_ZERO);
+ kdcomp->kdc_stream = compressor_init(kerneldumpcomp_write_cb,
+ COMPRESS_GZIP, di->maxiosize, kerneldump_gzlevel, di);
+ if (kdcomp->kdc_stream == NULL) {
+ free(kdcomp, M_DUMPER);
return (NULL);
}
- kdgz->kdgz_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP);
- return (kdgz);
+ kdcomp->kdc_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP);
+ return (kdcomp);
}
static void
-kerneldumpgz_destroy(struct dumperinfo *di)
+kerneldumpcomp_destroy(struct dumperinfo *di)
{
- struct kerneldumpgz *kdgz;
+ struct kerneldumpcomp *kdcomp;
- kdgz = di->kdgz;
- if (kdgz == NULL)
+ kdcomp = di->kdcomp;
+ if (kdcomp == NULL)
return;
- gzio_fini(kdgz->kdgz_stream);
- explicit_bzero(kdgz->kdgz_buf, di->maxiosize);
- free(kdgz->kdgz_buf, M_DUMPER);
- free(kdgz, M_DUMPER);
+ compressor_fini(kdcomp->kdc_stream);
+ explicit_bzero(kdcomp->kdc_buf, di->maxiosize);
+ free(kdcomp->kdc_buf, M_DUMPER);
+ free(kdcomp, M_DUMPER);
}
-#endif /* GZIO */
/* Registration of dumpers */
int
@@ -1041,14 +1036,14 @@ set_dumper(struct dumperinfo *di, const char *devname,
return (EBUSY);
dumper = *di;
dumper.blockbuf = NULL;
- dumper.kdc = NULL;
- dumper.kdgz = NULL;
+ dumper.kdcrypto = NULL;
+ dumper.kdcomp = NULL;
if (encryption != KERNELDUMP_ENC_NONE) {
#ifdef EKCD
- dumper.kdc = kerneldumpcrypto_create(di->blocksize, encryption,
- key, encryptedkeysize, encryptedkey);
- if (dumper.kdc == NULL) {
+ dumper.kdcrypto = kerneldumpcrypto_create(di->blocksize,
+ encryption, key, encryptedkeysize, encryptedkey);
+ if (dumper.kdcrypto == NULL) {
error = EINVAL;
goto cleanup;
}
@@ -1065,7 +1060,6 @@ set_dumper(struct dumperinfo *di, const char *devname,
}
if (compression != KERNELDUMP_COMP_NONE) {
-#ifdef GZIO
/*
* We currently can't support simultaneous encryption and
* compression.
@@ -1074,31 +1068,25 @@ set_dumper(struct dumperinfo *di, const char *devname,
error = EOPNOTSUPP;
goto cleanup;
}
- dumper.kdgz = kerneldumpgz_create(&dumper, compression);
- if (dumper.kdgz == NULL) {
+ dumper.kdcomp = kerneldumpcomp_create(&dumper, compression);
+ if (dumper.kdcomp == NULL) {
error = EINVAL;
goto cleanup;
}
-#else
- error = EOPNOTSUPP;
- goto cleanup;
-#endif
}
dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
return (0);
cleanup:
#ifdef EKCD
- if (dumper.kdc != NULL) {
- explicit_bzero(dumper.kdc, sizeof(*dumper.kdc) +
- dumper.kdc->kdc_dumpkeysize);
- free(dumper.kdc, M_EKCD);
+ if (dumper.kdcrypto != NULL) {
+ explicit_bzero(dumper.kdcrypto, sizeof(*dumper.kdcrypto) +
+ dumper.kdcrypto->kdc_dumpkeysize);
+ free(dumper.kdcrypto, M_EKCD);
}
#endif
-#ifdef GZIO
- kerneldumpgz_destroy(&dumper);
-#endif
+ kerneldumpcomp_destroy(&dumper);
if (dumper.blockbuf != NULL) {
explicit_bzero(dumper.blockbuf, dumper.blocksize);
@@ -1168,7 +1156,7 @@ dump_encrypted_write(struct dumperinfo *di, void *virt
int error;
size_t nbytes;
- kdc = di->kdc;
+ kdc = di->kdcrypto;
while (length > 0) {
nbytes = MIN(length, sizeof(buf));
@@ -1194,7 +1182,7 @@ dump_write_key(struct dumperinfo *di, off_t offset)
{
struct kerneldumpcrypto *kdc;
- kdc = di->kdc;
+ kdc = di->kdcrypto;
if (kdc == NULL)
return (0);
return (dump_write(di, kdc->kdc_dumpkey, 0, offset,
@@ -1202,9 +1190,8 @@ dump_write_key(struct dumperinfo *di, off_t offset)
}
#endif /* EKCD */
-#ifdef GZIO
static int
-kerneldumpgz_write_cb(void *base, size_t length, off_t offset, void *arg)
+kerneldumpcomp_write_cb(void *base, size_t length, off_t offset, void *arg)
{
struct dumperinfo *di;
size_t resid, rlength;
@@ -1227,12 +1214,11 @@ kerneldumpgz_write_cb(void *base, size_t length, off_t
}
resid = length - rlength;
memmove(di->blockbuf, (uint8_t *)base + rlength, resid);
- di->kdgz->kdgz_resid = resid;
+ di->kdcomp->kdc_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
@@ -1290,10 +1276,10 @@ dump_start(struct dumperinfo *di, struct kerneldumphea
uint32_t keysize;
#ifdef EKCD
- int error = kerneldumpcrypto_init(di->kdc);
+ int error = kerneldumpcrypto_init(di->kdcrypto);
if (error != 0)
return (error);
- keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
+ keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
#else
keysize = 0;
#endif
@@ -1301,8 +1287,7 @@ dump_start(struct dumperinfo *di, struct kerneldumphea
dumpextent = dtoh64(kdh->dumpextent);
if (di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
keysize) {
-#ifdef GZIO
- if (di->kdgz != NULL) {
+ if (di->kdcomp != NULL) {
/*
* We don't yet know how much space the compressed dump
* will occupy, so try to use the whole swap partition
@@ -1315,7 +1300,6 @@ dump_start(struct dumperinfo *di, struct kerneldumphea
2 * di->blocksize - keysize;
kdh->dumpextent = htod64(dumpextent);
} else
-#endif
return (E2BIG);
}
@@ -1333,7 +1317,7 @@ _dump_append(struct dumperinfo *di, void *virtual, vm_
int error;
#ifdef EKCD
- if (di->kdc != NULL)
+ if (di->kdcrypto != NULL)
error = dump_encrypted_write(di, virtual, physical, di->dumpoff,
length);
else
@@ -1353,18 +1337,16 @@ 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 (di->kdcomp != NULL) {
+ /* Bounce through a buffer to avoid CRC errors. */
if (length > di->maxiosize)
return (EINVAL);
- buf = di->kdgz->kdgz_buf;
+ buf = di->kdcomp->kdc_buf;
memmove(buf, virtual, length);
- return (gzio_write(di->kdgz->kdgz_stream, buf, length));
+ return (compressor_write(di->kdcomp->kdc_stream, buf, length));
}
-#endif
return (_dump_append(di, virtual, physical, length));
}
@@ -1399,20 +1381,19 @@ dump_finish(struct dumperinfo *di, struct kerneldumphe
extent = dtoh64(kdh->dumpextent);
#ifdef EKCD
- keysize = kerneldumpcrypto_dumpkeysize(di->kdc);
+ keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
#else
keysize = 0;
#endif
-#ifdef GZIO
- if (di->kdgz != NULL) {
- error = gzio_flush(di->kdgz->kdgz_stream);
+ if (di->kdcomp != NULL) {
+ error = compressor_flush(di->kdcomp->kdc_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;
+ di->dumpoff += di->kdcomp->kdc_resid;
+ di->kdcomp->kdc_resid = 0;
}
if (error != 0)
return (error);
@@ -1426,9 +1407,8 @@ dump_finish(struct dumperinfo *di, struct kerneldumphe
kdh->parity = 0;
kdh->parity = kerneldump_parity(kdh);
- gzio_reset(di->kdgz->kdgz_stream);
+ compressor_reset(di->kdcomp->kdc_stream);
}
-#endif
/*
* Write kerneldump headers at the beginning and end of the dump extent.
@@ -1471,7 +1451,7 @@ dump_init_header(const struct dumperinfo *di, struct k
kdh->dumpextent = kdh->dumplength;
kdh->dumptime = htod64(time_second);
#ifdef EKCD
- kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(di->kdc));
+ kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(di->kdcrypto));
#else
kdh->dumpkeysize = 0;
#endif
@@ -1482,10 +1462,8 @@ dump_init_header(const struct dumperinfo *di, struct k
kdh->versionstring[dstsize - 2] = '\n';
if (panicstr != NULL)
strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring));
-#ifdef GZIO
- if (di->kdgz != NULL)
+ if (di->kdcomp != NULL)
kdh->compression = KERNELDUMP_COMP_GZIP;
-#endif
kdh->parity = kerneldump_parity(kdh);
}
Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c Mon Jan 8 20:14:16 2018 (r327706)
+++ head/sys/kern/kern_sig.c Mon Jan 8 21:27:41 2018 (r327707)
@@ -40,7 +40,6 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
-#include "opt_gzio.h"
#include "opt_ktrace.h"
#include <sys/param.h>
@@ -51,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/acct.h>
#include <sys/bus.h>
#include <sys/capsicum.h>
+#include <sys/compressor.h>
#include <sys/condvar.h>
#include <sys/event.h>
#include <sys/fcntl.h>
@@ -3255,18 +3255,31 @@ SYSCTL_PROC(_debug, OID_AUTO, ncores, CTLTYPE_INT|CTLF
#define GZ_SUFFIX ".gz"
-#ifdef GZIO
-static int compress_user_cores = 1;
-SYSCTL_INT(_kern, OID_AUTO, compress_user_cores, CTLFLAG_RWTUN,
- &compress_user_cores, 0, "Compression of user corefiles");
+int compress_user_cores = 0;
-int compress_user_cores_gzlevel = 6;
-SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_gzlevel, CTLFLAG_RWTUN,
- &compress_user_cores_gzlevel, 0, "Corefile gzip compression level");
-#else
-static int compress_user_cores = 0;
-#endif
+static int
+sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+ val = compress_user_cores;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (val != 0 && !compressor_avail(val))
+ return (EINVAL);
+ compress_user_cores = val;
+ return (error);
+}
+SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores, CTLTYPE_INT | CTLFLAG_RWTUN,
+ 0, sizeof(int), sysctl_compress_user_cores, "I",
+ "Enable compression of user corefiles (" __XSTRING(COMPRESS_GZIP) " = gzip)");
+
+int compress_user_cores_level = 6;
+SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN,
+ &compress_user_cores_level, 0,
+ "Corefile compression level");
+
/*
* Protect the access to corefilename[] by allproc_lock.
*/
@@ -3363,7 +3376,7 @@ corefile_open(const char *comm, uid_t uid, pid_t pid,
}
sx_sunlock(&corefilename_lock);
free(hostname, M_TEMP);
- if (compress)
+ if (compress == COMPRESS_GZIP)
sbuf_printf(&sb, GZ_SUFFIX);
if (sbuf_error(&sb) != 0) {
log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too "
@@ -3529,8 +3542,7 @@ coredump(struct thread *td)
PROC_UNLOCK(p);
if (p->p_sysent->sv_coredump != NULL) {
- error = p->p_sysent->sv_coredump(td, vp, limit,
- compress_user_cores ? IMGACT_CORE_COMPRESS : 0);
+ error = p->p_sysent->sv_coredump(td, vp, limit, 0);
} else {
error = ENOSYS;
}
Copied and modified: head/sys/kern/subr_compressor.c (from r327706, head/sys/kern/kern_gzio.c)
==============================================================================
--- head/sys/kern/kern_gzio.c Mon Jan 8 20:14:16 2018 (r327706, copy source)
+++ head/sys/kern/subr_compressor.c Mon Jan 8 21:27:41 2018 (r327707)
@@ -1,6 +1,8 @@
/*-
- * Copyright (c) 2014 Mark Johnston <markj at FreeBSD.org>
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
+ * Copyright (c) 2014, 2017 Mark Johnston <markj at FreeBSD.org>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
@@ -24,56 +26,88 @@
* SUCH DAMAGE.
*/
+/*
+ * Subroutines used for writing compressed user process and kernel core dumps.
+ */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_gzio.h"
+
#include <sys/param.h>
-#include <sys/gzio.h>
+#include <sys/compressor.h>
#include <sys/kernel.h>
+#include <sys/linker_set.h>
#include <sys/malloc.h>
-#include <sys/zutil.h>
-#define KERN_GZ_HDRLEN 10 /* gzip header length */
-#define KERN_GZ_TRAILERLEN 8 /* gzip trailer length */
-#define KERN_GZ_MAGIC1 0x1f /* first magic byte */
-#define KERN_GZ_MAGIC2 0x8b /* second magic byte */
+MALLOC_DEFINE(M_COMPRESS, "compressor", "kernel compression subroutines");
-MALLOC_DEFINE(M_GZIO, "gzio", "zlib state");
+struct compressor_methods {
+ int format;
+ void *(* const init)(size_t, int);
+ void (* const reset)(void *);
+ int (* const write)(void *, void *, size_t, compressor_cb_t, void *);
+ void (* const fini)(void *);
+};
-struct gzio_stream {
- uint8_t * gz_buffer; /* output buffer */
- size_t gz_bufsz; /* total buffer size */
+struct compressor {
+ const struct compressor_methods *methods;
+ compressor_cb_t cb;
+ void *priv;
+ void *arg;
+};
+
+SET_DECLARE(compressors, struct compressor_methods);
+
+#ifdef GZIO
+
+#include <sys/zutil.h>
+
+struct gz_stream {
+ uint8_t *gz_buffer; /* output buffer */
+ size_t gz_bufsz; /* output buffer size */
off_t gz_off; /* offset into the output stream */
- enum gzio_mode gz_mode; /* stream mode */
uint32_t gz_crc; /* stream CRC32 */
- gzio_cb gz_cb; /* output callback */
- void * gz_arg; /* private callback arg */
z_stream gz_stream; /* zlib state */
};
-static void * gz_alloc(void *, u_int, u_int);
-static void gz_free(void *, void *);
-static int gz_write(struct gzio_stream *, void *, u_int, int);
+static void *gz_init(size_t maxiosize, int level);
+static void gz_reset(void *stream);
+static int gz_write(void *stream, void *data, size_t len, compressor_cb_t,
+ void *);
+static void gz_fini(void *stream);
-struct gzio_stream *
-gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg)
+static void *
+gz_alloc(void *arg __unused, u_int n, u_int sz)
{
- struct gzio_stream *s;
- int error;
- if (bufsz < KERN_GZ_HDRLEN)
- return (NULL);
- if (mode != GZIO_DEFLATE)
- return (NULL);
+ /*
+ * Memory for zlib state is allocated using M_NODUMP since it may be
+ * used to compress a kernel dump, and we don't want zlib to attempt to
+ * compress its own state.
+ */
+ return (malloc(n * sz, M_COMPRESS, M_WAITOK | M_ZERO | M_NODUMP));
+}
- s = gz_alloc(NULL, 1, sizeof(*s));
- s->gz_bufsz = bufsz;
- s->gz_buffer = gz_alloc(NULL, 1, s->gz_bufsz);
- s->gz_mode = mode;
- s->gz_cb = cb;
- s->gz_arg = arg;
+static void
+gz_free(void *arg __unused, void *ptr)
+{
+ free(ptr, M_COMPRESS);
+}
+
+static void *
+gz_init(size_t maxiosize, int level)
+{
+ struct gz_stream *s;
+ int error;
+
+ s = gz_alloc(NULL, 1, roundup2(sizeof(*s), PAGE_SIZE));
+ s->gz_buffer = gz_alloc(NULL, 1, maxiosize);
+ s->gz_bufsz = maxiosize;
+
s->gz_stream.zalloc = gz_alloc;
s->gz_stream.zfree = gz_free;
s->gz_stream.opaque = NULL;
@@ -85,98 +119,57 @@ gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufs
if (error != 0)
goto fail;
- gzio_reset(s);
+ gz_reset(s);
return (s);
fail:
- gz_free(NULL, s->gz_buffer);
gz_free(NULL, s);
return (NULL);
}
-void
-gzio_reset(struct gzio_stream *s)
+static void
+gz_reset(void *stream)
{
+ struct gz_stream *s;
uint8_t *hdr;
+ const size_t hdrlen = 10;
- (void)deflateReset(&s->gz_stream);
-
+ s = stream;
s->gz_off = 0;
s->gz_crc = ~0U;
+ (void)deflateReset(&s->gz_stream);
s->gz_stream.avail_out = s->gz_bufsz;
s->gz_stream.next_out = s->gz_buffer;
/* Write the gzip header to the output buffer. */
hdr = s->gz_buffer;
- memset(hdr, 0, KERN_GZ_HDRLEN);
- hdr[0] = KERN_GZ_MAGIC1;
- hdr[1] = KERN_GZ_MAGIC2;
+ memset(hdr, 0, hdrlen);
+ hdr[0] = 0x1f;
+ hdr[1] = 0x8b;
hdr[2] = Z_DEFLATED;
hdr[9] = OS_CODE;
- s->gz_stream.next_out += KERN_GZ_HDRLEN;
- s->gz_stream.avail_out -= KERN_GZ_HDRLEN;
+ s->gz_stream.next_out += hdrlen;
+ s->gz_stream.avail_out -= hdrlen;
}
-int
-gzio_write(struct gzio_stream *s, void *data, u_int len)
-{
-
- return (gz_write(s, data, len, Z_NO_FLUSH));
-}
-
-int
-gzio_flush(struct gzio_stream *s)
-{
-
- return (gz_write(s, NULL, 0, Z_FINISH));
-}
-
-void
-gzio_fini(struct gzio_stream *s)
-{
-
- (void)deflateEnd(&s->gz_stream);
- gz_free(NULL, s->gz_buffer);
- gz_free(NULL, s);
-}
-
-static void *
-gz_alloc(void *arg __unused, u_int n, u_int sz)
-{
-
- /*
- * Memory for zlib state is allocated using M_NODUMP since it may be
- * used to compress a kernel dump, and we don't want zlib to attempt to
- * compress its own state.
- */
- return (malloc(n * sz, M_GZIO, M_WAITOK | M_ZERO | M_NODUMP));
-}
-
-static void
-gz_free(void *arg __unused, void *ptr)
-{
-
- free(ptr, M_GZIO);
-}
-
static int
-gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag)
+gz_write(void *stream, void *data, size_t len, compressor_cb_t cb,
+ void *arg)
{
- uint8_t trailer[KERN_GZ_TRAILERLEN];
+ struct gz_stream *s;
+ uint8_t trailer[8];
size_t room;
- int error, zerror;
+ int error, zerror, zflag;
- KASSERT(zflag == Z_FINISH || zflag == Z_NO_FLUSH,
- ("unexpected flag %d", zflag));
- KASSERT(s->gz_mode == GZIO_DEFLATE,
- ("invalid stream mode %d", s->gz_mode));
+ s = stream;
+ zflag = data == NULL ? Z_FINISH : Z_NO_FLUSH;
if (len > 0) {
s->gz_stream.avail_in = len;
- s->gz_stream.next_in = buf;
- s->gz_crc = crc32_raw(buf, len, s->gz_crc);
+ s->gz_stream.next_in = data;
+ s->gz_crc = crc32_raw(data, len, s->gz_crc);
} else
s->gz_crc ^= ~0U;
@@ -202,14 +195,13 @@ gz_write(struct gzio_stream *s, void *buf, u_int len,
((uint32_t *)trailer)[0] = s->gz_crc;
((uint32_t *)trailer)[1] =
s->gz_stream.total_in;
- room = MIN(KERN_GZ_TRAILERLEN,
+ room = MIN(sizeof(trailer),
s->gz_bufsz - len);
memcpy(s->gz_buffer + len, trailer, room);
len += room;
}
- error = s->gz_cb(s->gz_buffer, len, s->gz_off,
- s->gz_arg);
+ error = cb(s->gz_buffer, len, s->gz_off, arg);
if (error != 0)
break;
@@ -221,13 +213,103 @@ gz_write(struct gzio_stream *s, void *buf, u_int len,
* If we couldn't pack the trailer into the output
* buffer, write it out now.
*/
- if (zerror == Z_STREAM_END && room < KERN_GZ_TRAILERLEN)
- error = s->gz_cb(trailer + room,
- KERN_GZ_TRAILERLEN - room, s->gz_off,
- s->gz_arg);
+ if (zerror == Z_STREAM_END && room < sizeof(trailer))
+ error = cb(trailer + room,
+ sizeof(trailer) - room, s->gz_off, arg);
}
} while (zerror != Z_STREAM_END &&
(zflag == Z_FINISH || s->gz_stream.avail_in > 0));
return (error);
+}
+
+static void
+gz_fini(void *stream)
+{
+ struct gz_stream *s;
+
+ s = stream;
+ (void)deflateEnd(&s->gz_stream);
+ gz_free(NULL, s->gz_buffer);
+ gz_free(NULL, s);
+}
+
+struct compressor_methods gzip_methods = {
+ .format = COMPRESS_GZIP,
+ .init = gz_init,
+ .reset = gz_reset,
+ .write = gz_write,
+ .fini = gz_fini,
+};
+DATA_SET(compressors, gzip_methods);
+
+#endif /* GZIO */
+
+bool
+compressor_avail(int format)
+{
+ struct compressor_methods **iter;
+
+ SET_FOREACH(iter, compressors) {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list