diff options
| author | Joan V. C. <codeberg-hn80@joanvc.cat> | 2026-03-20 09:42:50 +0100 |
|---|---|---|
| committer | Efraim Flashner <efraim@flashner.co.il> | 2026-05-20 11:37:30 +0300 |
| commit | 3b7fd1e76698559f8575ffeeed116673bd00ade1 (patch) | |
| tree | e49b166727766800ed1005bd4baf792f667c1ec5 /gnu | |
| parent | 5912f01e976480b50c18c65f8236a998fc7db7f9 (diff) | |
gnu: services: Add btrfs-scrub-service-type.
* gnu/services/linux.scm (btrfs-scrub-configuration): New configuration
record.
(btrfs-scrub-service-type): New service type with custom actions.
(fstrim-/shepherd-calendar-event?): Refactor to avoid name collisions.
* doc/guix.texi: Add service documentation.
Change-Id: I04747914591a80cd535d2f79d35e08f68081b2fc
Signed-off-by: Joan Vilardaga Castro <codeberg-hn80@joanvc.cat>
Signed-off-by: Efraim Flashner <efraim@flashner.co.il>
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/services/linux.scm | 135 |
1 files changed, 132 insertions, 3 deletions
diff --git a/gnu/services/linux.scm b/gnu/services/linux.scm index 2284741a659..f6e74b60ff5 100644 --- a/gnu/services/linux.scm +++ b/gnu/services/linux.scm | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | ;;; Copyright © 2023 Felix Lechner <felix.lechner@lease-up.com> | 9 | ;;; Copyright © 2023 Felix Lechner <felix.lechner@lease-up.com> |
| 10 | ;;; Copyright © 2025 Edouard Klein <edk@beaver-labs.com> | 10 | ;;; Copyright © 2025 Edouard Klein <edk@beaver-labs.com> |
| 11 | ;;; Copyright © 2026 Giacomo Leidi <therewasa@fishinthecalculator.me> | 11 | ;;; Copyright © 2026 Giacomo Leidi <therewasa@fishinthecalculator.me> |
| 12 | ;;; Copyright © 2026 Joan Vilardaga Castro <codeberg-hn80@joanvc.cat> | ||
| 12 | ;;; | 13 | ;;; |
| 13 | ;;; This file is part of GNU Guix. | 14 | ;;; This file is part of GNU Guix. |
| 14 | ;;; | 15 | ;;; |
| @@ -52,7 +53,10 @@ | |||
| 52 | #:use-module (ice-9 format) | 53 | #:use-module (ice-9 format) |
| 53 | #:use-module (ice-9 match) | 54 | #:use-module (ice-9 match) |
| 54 | #:use-module (ice-9 string-fun) | 55 | #:use-module (ice-9 string-fun) |
| 55 | #:export (earlyoom-configuration | 56 | #:export (btrfs-scrub-configuration |
| 57 | btrfs-scrub-service-type | ||
| 58 | |||
| 59 | earlyoom-configuration | ||
| 56 | earlyoom-configuration? | 60 | earlyoom-configuration? |
| 57 | earlyoom-configuration-earlyoom | 61 | earlyoom-configuration-earlyoom |
| 58 | earlyoom-configuration-minimum-available-memory | 62 | earlyoom-configuration-minimum-available-memory |
| @@ -161,6 +165,131 @@ | |||
| 161 | 165 | ||
| 162 | 166 | ||
| 163 | ;;; | 167 | ;;; |
| 168 | ;;; BTRFS scrub. | ||
| 169 | ;;; | ||
| 170 | |||
| 171 | (define (btrfs-scrub-shepherd-calendar-event? x) | ||
| 172 | (or (string? x) (gexp? x))) | ||
| 173 | |||
| 174 | (define-maybe string (prefix btrfs-scrub-)) | ||
| 175 | |||
| 176 | (define-maybe list-of-strings (prefix btrfs-scrub-)) | ||
| 177 | |||
| 178 | (define (btrfs-scrub-serialize-string field-name value) | ||
| 179 | (if (maybe-value-set? value) | ||
| 180 | (list value) '())) | ||
| 181 | |||
| 182 | (define (btrfs-scrub-serialize-list-of-string field-name value) | ||
| 183 | (if (maybe-value-set? value) | ||
| 184 | value '())) | ||
| 185 | |||
| 186 | (define-configuration btrfs-scrub-configuration | ||
| 187 | (package | ||
| 188 | (file-like btrfs-progs) | ||
| 189 | "The package providing the @command{btrfs} command." empty-serializer) | ||
| 190 | (schedule (btrfs-scrub-shepherd-calendar-event "0 0 1-7 * 0") | ||
| 191 | "Schedule for launching @command{btrfs-scrub}, expressed as a string in | ||
| 192 | traditional cron syntax or as a gexp evaluating to a Shepherd calendar | ||
| 193 | event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). By default this | ||
| 194 | is set to run the 1st Sunday of the month, at 00:00." | ||
| 195 | empty-serializer) | ||
| 196 | ;; The following are btrfs-scrub-related options. | ||
| 197 | (to-scrub (maybe-string "/") | ||
| 198 | "Device to scrub. It will scrub the root (\"/\") if not given.") | ||
| 199 | (extra-arguments maybe-list-of-strings | ||
| 200 | "Extra options to append to @command{btrfs scrub start} | ||
| 201 | (run @samp{man btrfs-scrub} for more information). Keep in mind that, | ||
| 202 | by default, this service uses the @option{-B} flag (do not background and | ||
| 203 | print scrub statistics when finished).") | ||
| 204 | (prefix btrfs-scrub-)) | ||
| 205 | |||
| 206 | (define (serialize-btrfs-scrub-configuration config) | ||
| 207 | (list-transduce (compose (base-transducer config) tconcatenate) | ||
| 208 | rcons | ||
| 209 | btrfs-scrub-configuration-fields)) | ||
| 210 | |||
| 211 | |||
| 212 | (define (btrfs-scrub-template-action-procedure btrfs-bin cmd-args to-scrub) | ||
| 213 | "Template procedure to call the btrfs command, print it's outputs and return | ||
| 214 | it's exit code. Taken from | ||
| 215 | https://www.gnu.org/software/guile/manual/html_node/Processes.html#index-spawn" | ||
| 216 | #~(lambda (_ . args) | ||
| 217 | (let* ((stdout-in-out (pipe)) (stderr-in-out (pipe)) | ||
| 218 | (argv (append (list #$btrfs-bin) '#$cmd-args '(#$to-scrub))) | ||
| 219 | (pid (spawn #$btrfs-bin argv | ||
| 220 | #:output (cdr stdout-in-out) | ||
| 221 | #:error (cdr stderr-in-out)))) | ||
| 222 | (close-port (cdr stdout-in-out)) | ||
| 223 | (close-port (cdr stderr-in-out)) | ||
| 224 | (display (get-string-all (car stdout-in-out))) | ||
| 225 | ;; Redirect stderr to stdout to make it printable for "herd" | ||
| 226 | (display (get-string-all (car stderr-in-out))) | ||
| 227 | (close-port (car stdout-in-out)) | ||
| 228 | (close-port (car stderr-in-out)) | ||
| 229 | (let* ((status (waitpid pid)) (exit-val (status:exit-val (cdr status)))) | ||
| 230 | (= EXIT_SUCCESS exit-val))))) | ||
| 231 | |||
| 232 | |||
| 233 | (define (btrfs-scrub-status-action-procedure btrfs-bin to-scrub) | ||
| 234 | "Return a procedure to check the status of the current BTRFS scrub." | ||
| 235 | (btrfs-scrub-template-action-procedure btrfs-bin '("scrub" "status") to-scrub)) | ||
| 236 | |||
| 237 | (define (btrfs-scrub-cancel-action-procedure btrfs-bin to-scrub) | ||
| 238 | "Return a procedure to always cancel the current BTRFS scrub." | ||
| 239 | (btrfs-scrub-template-action-procedure btrfs-bin '("scrub" "cancel") to-scrub)) | ||
| 240 | |||
| 241 | (define (btrfs-scrub-extra-actions btrfs-bin to-scrub) | ||
| 242 | (list shepherd-trigger-action | ||
| 243 | (shepherd-action (name 'scrub-status) | ||
| 244 | (documentation | ||
| 245 | "Print the status of the scrubing process.") | ||
| 246 | (procedure (btrfs-scrub-status-action-procedure | ||
| 247 | btrfs-bin | ||
| 248 | to-scrub))) | ||
| 249 | (shepherd-action (name 'cancel) | ||
| 250 | (documentation | ||
| 251 | "Cancel the current scrub (it's an alias for stop).") | ||
| 252 | (procedure (btrfs-scrub-cancel-action-procedure | ||
| 253 | btrfs-bin | ||
| 254 | to-scrub))))) | ||
| 255 | |||
| 256 | |||
| 257 | (define (btrfs-scrub-shepherd-services config) | ||
| 258 | (match-record config <btrfs-scrub-configuration> | ||
| 259 | (package schedule to-scrub) | ||
| 260 | (let ((btrfs-bin (file-append package "/bin/btrfs"))) | ||
| 261 | (list (shepherd-service | ||
| 262 | (provision (list (string->symbol (string-append "btrfs-scrub-" to-scrub)))) | ||
| 263 | (requirement '(user-processes)) | ||
| 264 | (modules '((shepherd service timer) | ||
| 265 | (ice-9 popen) | ||
| 266 | (ice-9 textual-ports))) | ||
| 267 | (start #~(make-timer-constructor | ||
| 268 | #$(if (string? schedule) | ||
| 269 | #~(cron-string->calendar-event #$schedule) | ||
| 270 | schedule) | ||
| 271 | (command (list #$btrfs-bin | ||
| 272 | "scrub" | ||
| 273 | "start" | ||
| 274 | "-B" | ||
| 275 | #$@(serialize-btrfs-scrub-configuration config))) | ||
| 276 | #:wait-for-termination? #t)) | ||
| 277 | (stop (btrfs-scrub-cancel-action-procedure btrfs-bin to-scrub)) | ||
| 278 | (documentation "Periodically run the 'btrfs-scrub' command.") | ||
| 279 | (actions (btrfs-scrub-extra-actions btrfs-bin to-scrub))))))) | ||
| 280 | |||
| 281 | |||
| 282 | (define btrfs-scrub-service-type | ||
| 283 | (service-type (name 'btrfs-scrub) | ||
| 284 | (extensions (list (service-extension | ||
| 285 | shepherd-root-service-type | ||
| 286 | btrfs-scrub-shepherd-services))) | ||
| 287 | (description | ||
| 288 | "Verify the block checksums of a BTRFS filesystem.") | ||
| 289 | (default-value (btrfs-scrub-configuration)))) | ||
| 290 | |||
| 291 | |||
| 292 | ;;; | ||
| 164 | ;;; Early OOM daemon. | 293 | ;;; Early OOM daemon. |
| 165 | ;;; | 294 | ;;; |
| 166 | 295 | ||
| @@ -251,7 +380,7 @@ representation." | |||
| 251 | ;;; fstrim | 380 | ;;; fstrim |
| 252 | ;;; | 381 | ;;; |
| 253 | 382 | ||
| 254 | (define (shepherd-calendar-event? x) | 383 | (define (fstrim-shepherd-calendar-event? x) |
| 255 | (or (string? x) (gexp? x))) | 384 | (or (string? x) (gexp? x))) |
| 256 | 385 | ||
| 257 | (define-maybe list-of-strings (prefix fstrim-)) | 386 | (define-maybe list-of-strings (prefix fstrim-)) |
| @@ -271,7 +400,7 @@ representation." | |||
| 271 | "The package providing the @command{fstrim} command." | 400 | "The package providing the @command{fstrim} command." |
| 272 | empty-serializer) | 401 | empty-serializer) |
| 273 | (schedule | 402 | (schedule |
| 274 | (shepherd-calendar-event "0 0 * * 0") | 403 | (fstrim-shepherd-calendar-event "0 0 * * 0") |
| 275 | "Schedule for launching @command{fstrim}, expressed as a string in | 404 | "Schedule for launching @command{fstrim}, expressed as a string in |
| 276 | traditional cron syntax or as a gexp evaluating to a Shepherd calendar | 405 | traditional cron syntax or as a gexp evaluating to a Shepherd calendar |
| 277 | event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). By default this | 406 | event (@pxref{Timers,,, shepherd, The GNU Shepherd Manual}). By default this |
