summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Cournoyer <maxim.cournoyer@gmail.com>2024-05-12 20:51:50 -0400
committerMaxim Cournoyer <maxim.cournoyer@gmail.com>2024-05-29 22:01:23 -0400
commitafacfa33ec4b52cb9ffb9b0a7a0c1e68cf264673 (patch)
tree9d811f1d85d4ae892604ca421d653ea53fb654a0
parentb72b6063cebbcfd64d43f5b05ba8470eb11c3f65 (diff)
gnu: linux-libre: Enable Zstd compression of kernel modules.
This brings the on disk size of the kernel from 164 MiB to 144 MiB, or about 12%. * gnu/packages/linux.scm (default-extra-linux-options) [version>=5.13]: Enable CONFIG_MODULE_COMPRESS_ZSTD, else CONFIG_MODULE_COMPRESS_GZIP. (make-linux-libre*) [phases] {set-environment}: Set ZSTD_CLEVEL environment variable to 19. [native-inputs]: Add zstd. * gnu/build/linux-modules.scm (module-regex): Add .zst to regexp. Update doc. (modinfo-section-contents): Extend support to Zstd compressed module. (dot-ko): Register the 'zstd compression type. (ensure-dot-ko, file-name->module-name, load-linux-module*) (module-name->file-name/guess, write-module-name-database) (write-module-alias-database, write-module-device-database): Update doc. (module-name-lookup): Also consider zstd-compressed modules. * gnu/installer.scm (installer-program): Add guile-zstd extension to gexp. * gnu/system/linux-initrd.scm (flat-linux-module-directory): Likewise. Decompress zstd-compressed modules for use in initrd. * guix/profiles.scm (linux-module-database): Add guile-zstd extension to gexp. Change-Id: Ide899dc5c58ea5033583b1a91a92c025fc8d901a
-rw-r--r--gnu/build/linux-modules.scm62
-rw-r--r--gnu/installer.scm1
-rw-r--r--gnu/packages/linux.scm13
-rw-r--r--gnu/system/linux-initrd.scm6
-rw-r--r--guix/profiles.scm7
5 files changed, 57 insertions, 32 deletions
diff --git a/gnu/build/linux-modules.scm b/gnu/build/linux-modules.scm
index 68c32ff8738..32baf6c5259 100644
--- a/gnu/build/linux-modules.scm
+++ b/gnu/build/linux-modules.scm
@@ -3,6 +3,7 @@
3;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> 3;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
4;;; Copyright © 2018 Danny Milosavljevic <dannym@scratchpost.org> 4;;; Copyright © 2018 Danny Milosavljevic <dannym@scratchpost.org>
5;;; Copyright © 2023 Tobias Geerinckx-Rice <me@tobias.gr> 5;;; Copyright © 2023 Tobias Geerinckx-Rice <me@tobias.gr>
6;;; Copyright © 2024 Maxim Cournoyer <maxim.cournoyer@gmail.com>
6;;; 7;;;
7;;; This file is part of GNU Guix. 8;;; This file is part of GNU Guix.
8;;; 9;;;
@@ -26,6 +27,7 @@
26 #:use-module ((guix build utils) #:select (find-files invoke)) 27 #:use-module ((guix build utils) #:select (find-files invoke))
27 #:use-module (guix build union) 28 #:use-module (guix build union)
28 #:autoload (zlib) (call-with-gzip-input-port) 29 #:autoload (zlib) (call-with-gzip-input-port)
30 #:autoload (zstd) (call-with-zstd-input-port)
29 #:use-module (rnrs io ports) 31 #:use-module (rnrs io ports)
30 #:use-module (rnrs bytevectors) 32 #:use-module (rnrs bytevectors)
31 #:use-module (srfi srfi-1) 33 #:use-module (srfi srfi-1)
@@ -108,24 +110,29 @@ string list."
108 (cons (string->symbol (string-take str =)) 110 (cons (string->symbol (string-take str =))
109 (string-drop str (+ 1 =))))) 111 (string-drop str (+ 1 =)))))
110 112
111;; Matches kernel modules, without compression, with GZIP compression or with 113;; Matches kernel modules, without compression, with GZIP, XZ or ZSTD
112;; XZ compression. 114;; compression.
113(define module-regex "\\.ko(\\.gz|\\.xz)?$") 115(define module-regex "\\.ko(\\.gz|\\.xz|\\.zst)?$")
114 116
115(define (modinfo-section-contents file) 117(define (modinfo-section-contents file)
116 "Return the contents of the '.modinfo' section of FILE as a list of 118 "Return the contents of the '.modinfo' section of FILE as a list of
117key/value pairs.." 119key/value pairs.."
120 (define (decompress-file decompressor file)
121 (let ((port (open-file file "r0")))
122 (dynamic-wind
123 (lambda ()
124 #t)
125 (lambda ()
126 (decompressor port get-bytevector-all))
127 (lambda ()
128 (close-port port)))))
129
118 (define (get-bytevector file) 130 (define (get-bytevector file)
119 (cond 131 (cond
120 ((string-suffix? ".ko.gz" file) 132 ((string-suffix? ".ko.gz" file)
121 (let ((port (open-file file "r0"))) 133 (decompress-file call-with-gzip-input-port file))
122 (dynamic-wind 134 ((string-suffix? ".ko.zst" file)
123 (lambda () 135 (decompress-file call-with-zstd-input-port file))
124 #t)
125 (lambda ()
126 (call-with-gzip-input-port port get-bytevector-all))
127 (lambda ()
128 (close-port port)))))
129 (else 136 (else
130 (call-with-input-file file get-bytevector-all)))) 137 (call-with-input-file file get-bytevector-all))))
131 138
@@ -213,11 +220,12 @@ modules that can be postloaded, of the soft dependencies of module FILE."
213 (let ((suffix (match compression 220 (let ((suffix (match compression
214 ('xz ".ko.xz") 221 ('xz ".ko.xz")
215 ('gzip ".ko.gz") 222 ('gzip ".ko.gz")
223 ('zstd ".ko.zst")
216 (else ".ko")))) 224 (else ".ko"))))
217 (string-append name suffix))) 225 (string-append name suffix)))
218 226
219(define (ensure-dot-ko name compression) 227(define (ensure-dot-ko name compression)
220 "Return NAME with a '.ko[.gz|.xz]' suffix appended, unless it already has 228 "Return NAME with a '.ko[.gz|.xz|.zst]' suffix appended, unless it already has
221it." 229it."
222 (if (string-contains name ".ko") 230 (if (string-contains name ".ko")
223 name 231 name
@@ -235,7 +243,7 @@ underscores."
235 243
236(define (file-name->module-name file) 244(define (file-name->module-name file)
237 "Return the module name corresponding to FILE, stripping the trailing 245 "Return the module name corresponding to FILE, stripping the trailing
238'.ko[.gz|.xz]' and normalizing it." 246'.ko[.gz|.xz|.zst]' and normalizing it."
239 (normalize-module-name (strip-extension (basename file)))) 247 (normalize-module-name (strip-extension (basename file))))
240 248
241(define (find-module-file directory module) 249(define (find-module-file directory module)
@@ -333,11 +341,11 @@ not a file name."
333 (recursive? #t) 341 (recursive? #t)
334 (lookup-module dot-ko) 342 (lookup-module dot-ko)
335 (black-list (module-black-list))) 343 (black-list (module-black-list)))
336 "Load Linux module from FILE, the name of a '.ko[.gz|.xz]' file; return true 344 "Load Linux module from FILE, the name of a '.ko[.gz|.xz|.zst]' file; return
337on success, false otherwise. When RECURSIVE? is true, load its dependencies 345true on success, false otherwise. When RECURSIVE? is true, load its
338first (à la 'modprobe'.) The actual files containing modules depended on are 346dependencies first (à la 'modprobe'.) The actual files containing modules
339obtained by calling LOOKUP-MODULE with the module name. Modules whose name 347depended on are obtained by calling LOOKUP-MODULE with the module name.
340appears in BLACK-LIST are not loaded." 348Modules whose name appears in BLACK-LIST are not loaded."
341 (define (black-listed? module) 349 (define (black-listed? module)
342 (let ((result (member module black-list))) 350 (let ((result (member module black-list)))
343 (when result 351 (when result
@@ -695,7 +703,7 @@ are required to access DEVICE."
695 "Guess the file name corresponding to NAME, a module name. That doesn't 703 "Guess the file name corresponding to NAME, a module name. That doesn't
696always work because sometimes underscores in NAME map to hyphens (e.g., 704always work because sometimes underscores in NAME map to hyphens (e.g.,
697\"input-leds.ko\"), sometimes not (e.g., \"mac_hid.ko\"). If the module is 705\"input-leds.ko\"), sometimes not (e.g., \"mac_hid.ko\"). If the module is
698compressed then COMPRESSED can be set to 'xz or 'gzip, depending on the 706compressed then COMPRESSED can be set to 'zstd, 'xz or 'gzip, depending on the
699compression type." 707compression type."
700 (string-append directory "/" (ensure-dot-ko name compression))) 708 (string-append directory "/" (ensure-dot-ko name compression)))
701 709
@@ -707,6 +715,8 @@ compression type."
707 (let ((names (list 715 (let ((names (list
708 (module-name->file-name/guess directory name) 716 (module-name->file-name/guess directory name)
709 (module-name->file-name/guess directory name 717 (module-name->file-name/guess directory name
718 #:compression 'zstd)
719 (module-name->file-name/guess directory name
710 #:compression 'xz) 720 #:compression 'xz)
711 (module-name->file-name/guess directory name 721 (module-name->file-name/guess directory name
712 #:compression 'gzip)))) 722 #:compression 'gzip))))
@@ -729,8 +739,8 @@ compression type."
729 739
730(define (write-module-name-database directory) 740(define (write-module-name-database directory)
731 "Write a database that maps \"module names\" as they appear in the relevant 741 "Write a database that maps \"module names\" as they appear in the relevant
732ELF section of '.ko[.gz|.xz]' files, to actual file names. This format is 742ELF section of '.ko[.gz|.xz|.zst]' files, to actual file names. This format
733Guix-specific. It aims to deal with inconsistent naming, in particular 743is Guix-specific. It aims to deal with inconsistent naming, in particular
734hyphens vs. underscores." 744hyphens vs. underscores."
735 (define mapping 745 (define mapping
736 (map (lambda (file) 746 (map (lambda (file)
@@ -749,8 +759,8 @@ hyphens vs. underscores."
749 (pretty-print mapping port)))) 759 (pretty-print mapping port))))
750 760
751(define (write-module-alias-database directory) 761(define (write-module-alias-database directory)
752 "Traverse the '.ko[.gz|.xz]' files in DIRECTORY and create the corresponding 762 "Traverse the '.ko[.gz|.xz|.zst]' files in DIRECTORY and create the
753'modules.alias' file." 763corresponding 'modules.alias' file."
754 (define aliases 764 (define aliases
755 (map (lambda (file) 765 (map (lambda (file)
756 (cons (file-name->module-name file) (module-aliases file))) 766 (cons (file-name->module-name file) (module-aliases file)))
@@ -796,9 +806,9 @@ are found, return a tuple (DEVNAME TYPE MAJOR MINOR), otherwise return #f."
796 (char-set-complement (char-set #\-))) 806 (char-set-complement (char-set #\-)))
797 807
798(define (write-module-device-database directory) 808(define (write-module-device-database directory)
799 "Traverse the '.ko[.gz|.xz]' files in DIRECTORY and create the corresponding 809 "Traverse the '.ko[.gz|.xz|.zst]' files in DIRECTORY and create the
800'modules.devname' file. This file contains information about modules that can 810corresponding 'modules.devname' file. This file contains information about
801be loaded on-demand, such as file system modules." 811modules that can be loaded on-demand, such as file system modules."
802 (define aliases 812 (define aliases
803 (filter-map (lambda (file) 813 (filter-map (lambda (file)
804 (match (aliases->device-tuple (module-aliases file)) 814 (match (aliases->device-tuple (module-aliases file))
diff --git a/gnu/installer.scm b/gnu/installer.scm
index 3b06b4f01b7..3792fc7e350 100644
--- a/gnu/installer.scm
+++ b/gnu/installer.scm
@@ -386,6 +386,7 @@ purposes."
386 guile-json-3 guile-git guile-webutils 386 guile-json-3 guile-git guile-webutils
387 guile-gnutls 387 guile-gnutls
388 guile-zlib ;for (gnu build linux-modules) 388 guile-zlib ;for (gnu build linux-modules)
389 guile-zstd ;for (gnu build linux-modules)
389 (current-guix)) 390 (current-guix))
390 (with-imported-modules `(,@(source-module-closure 391 (with-imported-modules `(,@(source-module-closure
391 `(,@modules 392 `(,@modules
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index db2b0f4bda6..2575f687da2 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -874,6 +874,10 @@ ARCH and optionally VARIANT, or #f if there is no such configuration."
874 ,@(if (version>=? version "5.13") 874 ,@(if (version>=? version "5.13")
875 '(("BPF_UNPRIV_DEFAULT_OFF" . #t)) 875 '(("BPF_UNPRIV_DEFAULT_OFF" . #t))
876 '()) 876 '())
877 ;; Compress kernel modules via Zstd.
878 ,(if (version>=? version "5.13")
879 '("CONFIG_MODULE_COMPRESS_ZSTD" . #t)
880 '("CONFIG_MODULE_COMPRESS_GZIP" . #t))
877 ;; Some very mild hardening. 881 ;; Some very mild hardening.
878 ("CONFIG_SECURITY_DMESG_RESTRICT" . #t) 882 ("CONFIG_SECURITY_DMESG_RESTRICT" . #t)
879 ;; All kernels should have NAMESPACES options enabled 883 ;; All kernels should have NAMESPACES options enabled
@@ -1063,7 +1067,10 @@ ARCH and optionally VARIANT, or #f if there is no such configuration."
1063 "EXTRAVERSION ?=")) 1067 "EXTRAVERSION ?="))
1064 (setenv "EXTRAVERSION" 1068 (setenv "EXTRAVERSION"
1065 #$(and extra-version 1069 #$(and extra-version
1066 (string-append "-" extra-version))))) 1070 (string-append "-" extra-version)))
1071 ;; Use the maximum compression available for Zstd-compressed
1072 ;; modules.
1073 (setenv "ZSTD_CLEVEL" "19")))
1067 (replace 'configure 1074 (replace 'configure
1068 (lambda _ 1075 (lambda _
1069 (let ((config 1076 (let ((config
@@ -1157,7 +1164,9 @@ ARCH and optionally VARIANT, or #f if there is no such configuration."
1157 ;; support. 1164 ;; support.
1158 dwarves ;for pahole 1165 dwarves ;for pahole
1159 python-wrapper 1166 python-wrapper
1160 zlib)) 1167 zlib
1168 ;; For Zstd compression of kernel modules.
1169 zstd))
1161 (home-page "https://www.gnu.org/software/linux-libre/") 1170 (home-page "https://www.gnu.org/software/linux-libre/")
1162 (synopsis "100% free redistribution of a cleaned Linux kernel") 1171 (synopsis "100% free redistribution of a cleaned Linux kernel")
1163 (description "GNU Linux-Libre is a free (as in freedom) variant of the 1172 (description "GNU Linux-Libre is a free (as in freedom) variant of the
diff --git a/gnu/system/linux-initrd.scm b/gnu/system/linux-initrd.scm
index d448c789181..f902637e484 100644
--- a/gnu/system/linux-initrd.scm
+++ b/gnu/system/linux-initrd.scm
@@ -128,7 +128,7 @@ MODULES and taken from LINUX."
128 128
129 (define build-exp 129 (define build-exp
130 (with-imported-modules imported-modules 130 (with-imported-modules imported-modules
131 (with-extensions (list guile-zlib) 131 (with-extensions (list guile-zlib guile-zstd)
132 #~(begin 132 #~(begin
133 (use-modules (gnu build linux-modules) 133 (use-modules (gnu build linux-modules)
134 (guix build utils) 134 (guix build utils)
@@ -168,7 +168,9 @@ MODULES and taken from LINUX."
168 ;; is already gzipped as a whole. 168 ;; is already gzipped as a whole.
169 (cond 169 (cond
170 ((string-contains file ".ko.gz") 170 ((string-contains file ".ko.gz")
171 (invoke #+(file-append gzip "/bin/gunzip") file)))) 171 (invoke #+(file-append gzip "/bin/gunzip") file))
172 ((string-contains file ".ko.zst")
173 (invoke #+(file-append zstd "/bin/zstd") "-d" file))))
172 174
173 (mkdir #$output) 175 (mkdir #$output)
174 (for-each (lambda (module) 176 (for-each (lambda (module)
diff --git a/guix/profiles.scm b/guix/profiles.scm
index d41802422bc..864ed02b6de 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -7,7 +7,7 @@
7;;; Copyright © 2016, 2017, 2018, 2019, 2021, 2022 Ricardo Wurmus <rekado@elephly.net> 7;;; Copyright © 2016, 2017, 2018, 2019, 2021, 2022 Ricardo Wurmus <rekado@elephly.net>
8;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com> 8;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
9;;; Copyright © 2017 Huang Ying <huang.ying.caritas@gmail.com> 9;;; Copyright © 2017 Huang Ying <huang.ying.caritas@gmail.com>
10;;; Copyright © 2017, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com> 10;;; Copyright © 2017, 2021, 2024 Maxim Cournoyer <maxim.cournoyer@gmail.com>
11;;; Copyright © 2019 Kyle Meyer <kyle@kyleam.com> 11;;; Copyright © 2019 Kyle Meyer <kyle@kyleam.com>
12;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com> 12;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com>
13;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org> 13;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
@@ -1487,11 +1487,14 @@ This is meant to be used as a profile hook."
1487 (define guile-zlib 1487 (define guile-zlib
1488 (module-ref (resolve-interface '(gnu packages guile)) 'guile-zlib)) 1488 (module-ref (resolve-interface '(gnu packages guile)) 'guile-zlib))
1489 1489
1490 (define guile-zstd
1491 (module-ref (resolve-interface '(gnu packages guile)) 'guile-zstd))
1492
1490 (define build 1493 (define build
1491 (with-imported-modules (source-module-closure 1494 (with-imported-modules (source-module-closure
1492 '((guix build utils) 1495 '((guix build utils)
1493 (gnu build linux-modules))) 1496 (gnu build linux-modules)))
1494 (with-extensions (list guile-zlib) 1497 (with-extensions (list guile-zlib guile-zstd)
1495 #~(begin 1498 #~(begin
1496 (use-modules (ice-9 ftw) 1499 (use-modules (ice-9 ftw)
1497 (ice-9 match) 1500 (ice-9 match)