services: Add zram-device-service.

* gnu/services/linux.scm (<zram-device-configuration>): New record.
(zram-device-service-type): New variable.
* doc/guix.texi (Linux Services): Document it.
* tests/services/linux.scm (zram-swap-device-test): New tests.
This commit is contained in:
Efraim Flashner 2020-07-22 21:07:31 +03:00
parent a05edef2ac
commit 587e0d911d
No known key found for this signature in database
GPG Key ID: 41AAE7DCCA3D8351
3 changed files with 162 additions and 1 deletions

View File

@ -27283,6 +27283,51 @@ parameters, can be done as follow:
@end lisp
@end deffn
@cindex zram
@cindex compressed swap
@cindex Compressed RAM-based block devices
@subsubheading Zram Device Service
The Zram device service provides a compressed swap device in system
memory. The Linux Kernel documentation has more information about
@uref{https://www.kernel.org/doc/html/latest/admin-guide/blockdev/zram.html,zram}
devices.
@deffn {Scheme Variable} zram-device-service-type
This service creates the zram block device, formats it as swap and
enables it as a swap device. The service's value is a
@code{zram-device-configuration} record.
@deftp {Data Type} zram-device-configuration
This is the data type representing the configuration for the zram-device
service.
@table @asis
@item @code{size} (default @var{"1G"})
This is the amount of space you wish to provide for the zram device. It
accepts a string and can be a number of bytes or use a suffix, eg.:
@var{"512M"} or @var{1024000}.
@item @code{compression-algorithm} (default @var{'lzo})
This is the compression algorithm you wish to use. It is difficult to
list all the possible compression options, but common ones supported by
Guix's Linux Libre Kernel include @var{'lzo}, @var{'lz4} and @var{'zstd}.
@item @code{memory-limit} (default @var{0})
This is the maximum amount of memory which the zram device can use.
Setting it to '0' disables the limit. While it is generally expected
that compression will be 2:1, it is possible that uncompressable data
can be written to swap and this is a method to limit how much memory can
be used. It accepts a string and can be a number of bytes or use a
suffix, eg.: @var{"2G"}.
@item @code{priority} (default @var{-1})
This is the priority of the swap device created from the zram device.
@code{swapon} accepts values between -1 and 32767, with higher values
indicating higher priority. Higher priority swap will generally be used
first.
@end table
@end deftp
@end deffn
@node Hurd Services
@subsection Hurd Services

View File

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@ -22,6 +23,7 @@
#:use-module (guix records)
#:use-module (guix modules)
#:use-module (gnu services)
#:use-module (gnu services base)
#:use-module (gnu services shepherd)
#:use-module (gnu packages linux)
#:use-module (srfi srfi-1)
@ -42,7 +44,15 @@
earlyoom-configuration-send-notification-command
earlyoom-service-type
kernel-module-loader-service-type))
kernel-module-loader-service-type
zram-device-configuration
zram-device-configuration?
zram-device-configuration-size
zram-device-configuration-compression-algorithm
zram-device-configuration-memory-limit
zram-device-configuration-priority
zram-device-service-type))
;;;
@ -177,3 +187,72 @@ representation."
(compose concatenate)
(extend append)
(default-value '())))
;;;
;;; Kernel module loader.
;;;
(define-record-type* <zram-device-configuration>
zram-device-configuration make-zram-device-configuration
zram-device-configuration?
(size zram-device-configration-size
(default "1G")) ; string or integer
(compression-algorithm zram-device-configuration-compression-algorithm
(default 'lzo)) ; symbol
(memory-limit zram-device-configuration-memory-limit
(default 0)) ; string or integer
(priority zram-device-configuration-priority
(default -1))) ; integer
(define (zram-device-configuration->udev-string config)
"Translate a <zram-device-configuration> into a string which can be
placed in a udev rules file."
(match config
(($ <zram-device-configuration> size compression-algorithm memory-limit priority)
(string-append
"KERNEL==\"zram0\", "
"ATTR{comp_algorithm}=\"" (symbol->string compression-algorithm) "\" "
(if (not (or (equal? "0" size)
(equal? 0 size)))
(string-append "ATTR{disksize}=\"" (if (number? size)
(number->string size)
size)
"\" ")
"")
(if (not (or (equal? "0" memory-limit)
(equal? 0 memory-limit)))
(string-append "ATTR{mem_limit}=\"" (if (number? memory-limit)
(number->string memory-limit)
memory-limit)
"\" ")
"")
"RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" "
"RUN+=\"/run/current-system/profile/sbin/swapon "
(if (not (equal? -1 priority))
(string-append "--priority " (number->string priority) " ")
"")
"/dev/zram0\"\n"))))
(define %zram-device-config
`("modprobe.d/zram.conf"
,(plain-file "zram.conf"
"options zram num_devices=1")))
(define (zram-device-udev-rule config)
(file->udev-rule "99-zram.rules"
(plain-file "99-zram.rules"
(zram-device-configuration->udev-string config))))
(define zram-device-service-type
(service-type
(name 'zram)
(default-value (zram-device-configuration))
(extensions
(list (service-extension kernel-module-loader-service-type
(const (list "zram")))
(service-extension etc-service-type
(const (list %zram-device-config)))
(service-extension udev-service-type
(compose list zram-device-udev-rule))))
(description "Creates a zram swap device.")))

View File

@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
@ -54,4 +55,40 @@
"-N" "python \"/some/path/notify-all-users.py\"")
(earlyoom-configuration->command-line-args %earlyoom-configuration-sample))
;;;
;;; Zram swap device.
;;;
(define zram-device-configuration->udev-string
(@@ (gnu services linux) zram-device-configuration->udev-string))
(define %zram-swap-device-test-1
(zram-device-configuration
(size "2G")
(compression-algorithm 'zstd)
(memory-limit "1G")
(priority 42)))
(test-equal "zram-swap-device-test-1"
"KERNEL==\"zram0\", ATTR{comp_algorithm}=\"zstd\" ATTR{disksize}=\"2G\" ATTR{mem_limit}=\"1G\" RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" RUN+=\"/run/current-system/profile/sbin/swapon --priority 42 /dev/zram0\"\n"
(zram-device-configuration->udev-string %zram-swap-device-test-1))
(define %zram-swap-device-test-2
(zram-device-configuration
(size 1048576) ; 1M
(compression-algorithm 'lz4)))
(test-equal "zram-swap-device-test-2"
"KERNEL==\"zram0\", ATTR{comp_algorithm}=\"lz4\" ATTR{disksize}=\"1048576\" RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" RUN+=\"/run/current-system/profile/sbin/swapon /dev/zram0\"\n"
(zram-device-configuration->udev-string %zram-swap-device-test-2))
(define %zram-swap-device-test-3
(zram-device-configuration
(memory-limit (* 512 1000))))
(test-equal "zram-swap-device-test-3"
"KERNEL==\"zram0\", ATTR{comp_algorithm}=\"lzo\" ATTR{disksize}=\"1G\" ATTR{mem_limit}=\"512000\" RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" RUN+=\"/run/current-system/profile/sbin/swapon /dev/zram0\"\n"
(zram-device-configuration->udev-string %zram-swap-device-test-3))
(test-end "linux-services")