linux.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2020 Maxim Cournoyer <maxim.cournoyer@gmail.com>
  3. ;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
  4. ;;; Copyright © 2020, 2023 Efraim Flashner <efraim@flashner.co.il>
  5. ;;; Copyright © 2021 raid5atemyhomework <raid5atemyhomework@protonmail.com>
  6. ;;; Copyright © 2021 B. Wilson <elaexuotee@wilsonb.com>
  7. ;;; Copyright © 2022 Josselin Poiret <dev@jpoiret.xyz>
  8. ;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
  9. ;;;
  10. ;;; This file is part of GNU Guix.
  11. ;;;
  12. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  13. ;;; under the terms of the GNU General Public License as published by
  14. ;;; the Free Software Foundation; either version 3 of the License, or (at
  15. ;;; your option) any later version.
  16. ;;;
  17. ;;; GNU Guix is distributed in the hope that it will be useful, but
  18. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. ;;; GNU General Public License for more details.
  21. ;;;
  22. ;;; You should have received a copy of the GNU General Public License
  23. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  24. (define-module (gnu services linux)
  25. #:use-module (guix diagnostics)
  26. #:use-module (guix gexp)
  27. #:use-module (guix records)
  28. #:use-module (guix modules)
  29. #:use-module (guix i18n)
  30. #:use-module (guix ui)
  31. #:use-module (gnu services)
  32. #:use-module (gnu services admin)
  33. #:use-module (gnu services base)
  34. #:use-module (gnu services configuration)
  35. #:use-module (gnu services mcron)
  36. #:use-module (gnu services shepherd)
  37. #:use-module (gnu packages linux)
  38. #:use-module (srfi srfi-1)
  39. #:use-module (srfi srfi-26)
  40. #:use-module (srfi srfi-34)
  41. #:use-module (srfi srfi-35)
  42. #:use-module (ice-9 format)
  43. #:use-module (ice-9 match)
  44. #:export (earlyoom-configuration
  45. earlyoom-configuration?
  46. earlyoom-configuration-earlyoom
  47. earlyoom-configuration-minimum-available-memory
  48. earlyoom-configuration-minimum-free-swap
  49. earlyoom-configuration-prefer-regexp
  50. earlyoom-configuration-avoid-regexp
  51. earlyoom-configuration-memory-report-interval
  52. earlyoom-configuration-ignore-positive-oom-score-adj?
  53. earlyoom-configuration-show-debug-messages?
  54. earlyoom-configuration-send-notification-command
  55. earlyoom-service-type
  56. fstrim-configuration
  57. fstrim-configuration?
  58. fstrim-configuration-package
  59. fstrim-configuration-schedule
  60. fstrim-configuration-listed-in
  61. fstrim-configuration-verbose?
  62. fstrim-configuration-quiet-unsupported?
  63. fstrim-configuration-extra-arguments
  64. fstrim-service-type
  65. kernel-module-loader-service-type
  66. rasdaemon-configuration
  67. rasdaemon-configuration?
  68. rasdaemon-configuration-record?
  69. rasdaemon-service-type
  70. zram-device-configuration
  71. zram-device-configuration?
  72. zram-device-configuration-size
  73. zram-device-configuration-compression-algorithm
  74. zram-device-configuration-memory-limit
  75. zram-device-configuration-priority
  76. zram-device-service-type))
  77. ;;;
  78. ;;; Early OOM daemon.
  79. ;;;
  80. (define-record-type* <earlyoom-configuration>
  81. earlyoom-configuration make-earlyoom-configuration
  82. earlyoom-configuration?
  83. (earlyoom earlyoom-configuration-earlyoom
  84. (default earlyoom))
  85. (minimum-available-memory earlyoom-configuration-minimum-available-memory
  86. (default 10)) ; in percent
  87. (minimum-free-swap earlyoom-configuration-minimum-free-swap
  88. (default 10)) ; in percent
  89. (prefer-regexp earlyoom-configuration-prefer-regexp ; <string>
  90. (default #f))
  91. (avoid-regexp earlyoom-configuration-avoid-regexp ; <string>
  92. (default #f))
  93. (memory-report-interval earlyoom-configuration-memory-report-interval
  94. (default 0)) ; in seconds; 0 means disabled
  95. (ignore-positive-oom-score-adj?
  96. earlyoom-configuration-ignore-positive-oom-score-adj? (default #f))
  97. (run-with-higher-priority? earlyoom-configuration-run-with-higher-priority?
  98. (default #f))
  99. (show-debug-messages? earlyoom-configuration-show-debug-messages?
  100. (default #f))
  101. (send-notification-command
  102. earlyoom-configuration-send-notification-command ; <string>
  103. (default #f)))
  104. (define (earlyoom-configuration->command-line-args config)
  105. "Translate a <earlyoom-configuration> object to its command line arguments
  106. representation."
  107. (match config
  108. (($ <earlyoom-configuration> earlyoom minimum-available-memory
  109. minimum-free-swap prefer-regexp avoid-regexp
  110. memory-report-interval
  111. ignore-positive-oom-score-adj?
  112. run-with-higher-priority? show-debug-messages?
  113. send-notification-command)
  114. `(,(file-append earlyoom "/bin/earlyoom")
  115. ,@(if minimum-available-memory
  116. (list "-m" (format #f "~s" minimum-available-memory))
  117. '())
  118. ,@(if minimum-free-swap
  119. (list "-s" (format #f "~s" minimum-free-swap))
  120. '())
  121. ,@(if prefer-regexp
  122. (list "--prefer" prefer-regexp)
  123. '())
  124. ,@(if avoid-regexp
  125. (list "--avoid" avoid-regexp)
  126. '())
  127. "-r" ,(format #f "~s" memory-report-interval)
  128. ,@(if ignore-positive-oom-score-adj?
  129. (list "-i")
  130. '())
  131. ,@(if run-with-higher-priority?
  132. (list "-p")
  133. '())
  134. ,@(if show-debug-messages?
  135. (list "-d")
  136. '())
  137. ,@(if send-notification-command
  138. (list "-N" send-notification-command)
  139. '())))))
  140. (define (earlyoom-shepherd-service config)
  141. (shepherd-service
  142. (documentation "Run the Early OOM daemon.")
  143. (provision '(earlyoom))
  144. (start #~(make-forkexec-constructor
  145. '#$(earlyoom-configuration->command-line-args config)
  146. #:log-file "/var/log/earlyoom.log"))
  147. (stop #~(make-kill-destructor))))
  148. (define %earlyoom-log-rotation
  149. (list (log-rotation
  150. (files '("/var/log/earlyoom.log")))))
  151. (define earlyoom-service-type
  152. (service-type
  153. (name 'earlyoom)
  154. (default-value (earlyoom-configuration))
  155. (extensions
  156. (list (service-extension shepherd-root-service-type
  157. (compose list earlyoom-shepherd-service))
  158. (service-extension rottlog-service-type
  159. (const %earlyoom-log-rotation))))
  160. (description "Run @command{earlyoom}, the Early OOM daemon.")))
  161. ;;;
  162. ;;; fstrim
  163. ;;;
  164. (define (mcron-time? x)
  165. (or (procedure? x) (string? x) (list? x)))
  166. (define-maybe list-of-strings (prefix fstrim-))
  167. (define (fstrim-serialize-boolean field-name value)
  168. (list (format #f "~:[~;--~a~]" value
  169. ;; Drop trailing '?' character.
  170. (string-drop-right (symbol->string field-name) 1))))
  171. (define (fstrim-serialize-list-of-strings field-name value)
  172. (list (string-append "--" (symbol->string field-name))
  173. #~(string-join '#$value ":")))
  174. (define-configuration fstrim-configuration
  175. (package
  176. (file-like util-linux)
  177. "The package providing the @command{fstrim} command."
  178. empty-serializer)
  179. (schedule
  180. (mcron-time "0 0 * * 0")
  181. "Schedule for launching @command{fstrim}. This can be a procedure, a list
  182. or a string. For additional information, see @ref{Guile Syntax,,
  183. Job specification, mcron, the mcron manual}. By default this is set to run
  184. weekly on Sunday at 00:00."
  185. empty-serializer)
  186. ;; The following are fstrim-related options.
  187. (listed-in
  188. (maybe-list-of-strings '("/etc/fstab" "/proc/self/mountinfo"))
  189. ;; Note: documentation sourced from the fstrim manpage.
  190. "List of files in fstab or kernel mountinfo format. All missing or
  191. empty files are silently ignored. The evaluation of the list @emph{stops}
  192. after the first non-empty file. File systems with @code{X-fstrim.notrim} mount
  193. option in fstab are skipped.")
  194. (verbose?
  195. (boolean #t)
  196. "Verbose execution.")
  197. (quiet-unsupported?
  198. (boolean #t)
  199. "Suppress error messages if trim operation (ioctl) is unsupported.")
  200. (extra-arguments
  201. maybe-list-of-strings
  202. "Extra options to append to @command{fstrim} (run @samp{man fstrim} for
  203. more information)."
  204. (serializer
  205. (lambda (_ value)
  206. (if (maybe-value-set? value)
  207. value '()))))
  208. (prefix fstrim-))
  209. (define (serialize-fstrim-configuration config)
  210. (concatenate
  211. (filter list?
  212. (map (lambda (field)
  213. ((configuration-field-serializer field)
  214. (configuration-field-name field)
  215. ((configuration-field-getter field) config)))
  216. fstrim-configuration-fields))))
  217. (define (fstrim-mcron-job config)
  218. (match-record config <fstrim-configuration> (package schedule)
  219. #~(job
  220. ;; Note: The “if” below is to ensure that
  221. ;; lists are ungexp'd correctly since @var{schedule}
  222. ;; can be either a procedure, a string or a list.
  223. #$(if (list? schedule)
  224. #~'(#$@schedule)
  225. schedule)
  226. (lambda ()
  227. (system* #$(file-append package "/sbin/fstrim")
  228. #$@(serialize-fstrim-configuration config)))
  229. "fstrim")))
  230. (define fstrim-service-type
  231. (service-type
  232. (name 'fstrim)
  233. (extensions
  234. (list (service-extension mcron-service-type
  235. (compose list fstrim-mcron-job))))
  236. (description "Discard unused blocks from file systems.")
  237. (default-value (fstrim-configuration))))
  238. ;;;
  239. ;;; Kernel module loader.
  240. ;;;
  241. (define kernel-module-loader-shepherd-service
  242. (match-lambda
  243. ((and (? list? kernel-modules) ((? string?) ...))
  244. (shepherd-service
  245. (documentation "Load kernel modules.")
  246. (provision '(kernel-module-loader))
  247. (requirement '())
  248. (one-shot? #t)
  249. (modules `((srfi srfi-1)
  250. (srfi srfi-34)
  251. (srfi srfi-35)
  252. (rnrs io ports)
  253. ,@%default-modules))
  254. (start
  255. #~(lambda _
  256. (cond
  257. ((null? '#$kernel-modules) #t)
  258. ((file-exists? "/proc/sys/kernel/modprobe")
  259. (let ((modprobe (call-with-input-file
  260. "/proc/sys/kernel/modprobe" get-line)))
  261. (guard (c ((message-condition? c)
  262. (format (current-error-port) "~a~%"
  263. (condition-message c))
  264. #f))
  265. (every (lambda (module)
  266. (invoke/quiet modprobe "--" module))
  267. '#$kernel-modules))))
  268. (else
  269. (format (current-error-port) "error: ~a~%"
  270. "Kernel is missing loadable module support.")
  271. #f))))))))
  272. (define kernel-module-loader-service-type
  273. (service-type
  274. (name 'kernel-module-loader)
  275. (description "Load kernel modules.")
  276. (extensions
  277. (list (service-extension shepherd-root-service-type
  278. (compose list kernel-module-loader-shepherd-service))))
  279. (compose concatenate)
  280. (extend append)
  281. (default-value '())))
  282. ;;;
  283. ;;; Reliability, Availability, and Serviceability (RAS) daemon
  284. ;;;
  285. (define-record-type* <rasdaemon-configuration>
  286. rasdaemon-configuration make-rasdaemon-configuration
  287. rasdaemon-configuration?
  288. (record? rasdaemon-configuration-record? (default #f)))
  289. (define (rasdaemon-configuration->command-line-args config)
  290. "Translate <rasdaemon-configuration> to its command line arguments
  291. representation"
  292. (let ((record? (rasdaemon-configuration-record? config)))
  293. `(,(file-append rasdaemon "/sbin/rasdaemon")
  294. "--foreground" ,@(if record? '("--record") '()))))
  295. (define (rasdaemon-activation config)
  296. (let ((record? (rasdaemon-configuration-record? config))
  297. (rasdaemon-dir "/var/lib/rasdaemon"))
  298. (with-imported-modules '((guix build utils))
  299. #~(if #$record? (mkdir-p #$rasdaemon-dir)))))
  300. (define (rasdaemon-shepherd-service config)
  301. (shepherd-service
  302. (documentation "Run rasdaemon")
  303. (provision '(rasdaemon))
  304. (requirement '(syslogd))
  305. (start #~(make-forkexec-constructor
  306. '#$(rasdaemon-configuration->command-line-args config)))
  307. (stop #~(make-kill-destructor))))
  308. (define rasdaemon-service-type
  309. (service-type
  310. (name 'rasdaemon)
  311. (default-value (rasdaemon-configuration))
  312. (extensions
  313. (list (service-extension shepherd-root-service-type
  314. (compose list rasdaemon-shepherd-service))
  315. (service-extension activation-service-type rasdaemon-activation)))
  316. (compose concatenate)
  317. (description "Run @command{rasdaemon}, the RAS monitor")))
  318. ;;;
  319. ;;; Kernel module loader.
  320. ;;;
  321. (define-record-type* <zram-device-configuration>
  322. zram-device-configuration make-zram-device-configuration
  323. zram-device-configuration?
  324. (size zram-device-configuration-size
  325. (default "1G")) ; string or integer
  326. (compression-algorithm zram-device-configuration-compression-algorithm
  327. (default 'lzo)) ; symbol
  328. (memory-limit zram-device-configuration-memory-limit
  329. (default 0)) ; string or integer
  330. (priority zram-device-configuration-priority
  331. (default #f) ; integer | #f
  332. (delayed) ; to avoid printing the deprecation
  333. ; warning multiple times
  334. (sanitize warn-zram-priority-change)))
  335. (define-with-syntax-properties
  336. (warn-zram-priority-change (priority properties))
  337. (if (eqv? priority -1)
  338. (begin
  339. (warning (source-properties->location properties)
  340. (G_ "using -1 for zram priority is deprecated~%"))
  341. (display-hint (G_ "Use #f or leave as default instead (@pxref{Linux \
  342. Services})."))
  343. #f)
  344. priority))
  345. (define (zram-device-configuration->udev-string config)
  346. "Translate a <zram-device-configuration> into a string which can be
  347. placed in a udev rules file."
  348. (match config
  349. (($ <zram-device-configuration> size compression-algorithm memory-limit priority)
  350. (string-append
  351. "KERNEL==\"zram0\", "
  352. "ATTR{comp_algorithm}=\"" (symbol->string compression-algorithm) "\" "
  353. (if (not (or (equal? "0" size)
  354. (equal? 0 size)))
  355. (string-append "ATTR{disksize}=\"" (if (number? size)
  356. (number->string size)
  357. size)
  358. "\" ")
  359. "")
  360. (if (not (or (equal? "0" memory-limit)
  361. (equal? 0 memory-limit)))
  362. (string-append "ATTR{mem_limit}=\"" (if (number? memory-limit)
  363. (number->string memory-limit)
  364. memory-limit)
  365. "\" ")
  366. "")
  367. "RUN+=\"/run/current-system/profile/sbin/mkswap /dev/zram0\" "
  368. "RUN+=\"/run/current-system/profile/sbin/swapon "
  369. ;; TODO: Revert to simply use 'priority' after removing the deprecation
  370. ;; warning and the delayed property of the field.
  371. (let ((priority* (force priority)))
  372. (if priority*
  373. (format #f "--priority ~a " priority*)
  374. ""))
  375. "/dev/zram0\"\n"))))
  376. (define %zram-device-config
  377. `("modprobe.d/zram.conf"
  378. ,(plain-file "zram.conf"
  379. "options zram num_devices=1")))
  380. (define (zram-device-udev-rule config)
  381. (file->udev-rule "99-zram.rules"
  382. (plain-file "99-zram.rules"
  383. (zram-device-configuration->udev-string config))))
  384. (define zram-device-service-type
  385. (service-type
  386. (name 'zram)
  387. (default-value (zram-device-configuration))
  388. (extensions
  389. (list (service-extension kernel-module-loader-service-type
  390. (const (list "zram")))
  391. (service-extension etc-service-type
  392. (const (list %zram-device-config)))
  393. (service-extension udev-service-type
  394. (compose list zram-device-udev-rule))))
  395. (description "Creates a zram swap device.")))