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(&notelst);
@@ -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, &params);
-               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, &params);
+               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(&notelst)) != NULL) {
                TAILQ_REMOVE(&notelst, 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 <ma...@freebsd.org>
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
+ * Copyright (c) 2014, 2017 Mark Johnston <ma...@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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to