diff --git a/gnu/services/base.scm b/gnu/services/base.scm index a86e8e04c7..67eeecdf17 100644 --- a/gnu/services/base.scm +++ b/gnu/services/base.scm @@ -43,7 +43,8 @@ #:use-module (srfi srfi-26) #:use-module (ice-9 match) #:use-module (ice-9 format) - #:export (root-file-system-service + #:export (fstab-service-type + root-file-system-service file-system-service user-unmount-service device-mapping-service @@ -105,6 +106,48 @@ ;;; File systems. ;;; +(define (file-system->fstab-entry file-system) + "Return a @file{/etc/fstab} entry for @var{file-system}." + (string-append (case (file-system-title file-system) + ((label) + (string-append "LABEL=" (file-system-device file-system))) + ((uuid) + (string-append + "UUID=" + (uuid->string (file-system-device file-system)))) + (else + (file-system-device file-system))) + "\t" + (file-system-mount-point file-system) "\t" + (file-system-type file-system) "\t" + (or (file-system-options file-system) "defaults") "\t" + + ;; XXX: Omit the 'fs_freq' and 'fs_passno' fields because we + ;; don't have anything sensible to put in there. + )) + +(define (file-systems->fstab file-systems) + "Return a @file{/etc} entry for an @file{fstab} describing +@var{file-systems}." + `(("fstab" ,(plain-file "fstab" + (string-append + "\ +# This file was generated from your GuixSD configuration. Any changes +# will be lost upon reboot or reconfiguration.\n\n" + (string-join (map file-system->fstab-entry + file-systems) + "\n") + "\n"))))) + +(define fstab-service-type + ;; The /etc/fstab service. + (service-type (name 'fstab) + (extensions + (list (service-extension etc-service-type + file-systems->fstab))) + (compose identity) + (extend append))) + (define %root-file-system-dmd-service (dmd-service (documentation "Take care of the root file system.") @@ -170,70 +213,76 @@ FILE-SYSTEM." ((? file-system? fs) (file-system->dmd-service-name fs)))) +(define (file-system-dmd-service file-system) + "Return a list containing the dmd service for @var{file-system}." + (let ((target (file-system-mount-point file-system)) + (device (file-system-device file-system)) + (type (file-system-type file-system)) + (title (file-system-title file-system)) + (check? (file-system-check? file-system)) + (create? (file-system-create-mount-point? file-system)) + (dependencies (file-system-dependencies file-system))) + (list (dmd-service + (provision (list (file-system->dmd-service-name file-system))) + (requirement `(root-file-system + ,@(map dependency->dmd-service-name dependencies))) + (documentation "Check, mount, and unmount the given file system.") + (start #~(lambda args + ;; FIXME: Use or factorize with 'mount-file-system'. + (let ((device (canonicalize-device-spec #$device '#$title)) + (flags #$(mount-flags->bit-mask + (file-system-flags file-system)))) + #$(if create? + #~(mkdir-p #$target) + #~#t) + #$(if check? + #~(begin + ;; Make sure fsck.ext2 & co. can be found. + (setenv "PATH" + (string-append + #$e2fsprogs "/sbin:" + "/run/current-system/profile/sbin:" + (getenv "PATH"))) + (check-file-system device #$type)) + #~#t) + + (mount device #$target #$type flags + #$(file-system-options file-system)) + + ;; For read-only bind mounts, an extra remount is needed, + ;; as per , which still + ;; applies to Linux 4.0. + (when (and (= MS_BIND (logand flags MS_BIND)) + (= MS_RDONLY (logand flags MS_RDONLY))) + (mount device #$target #$type + (logior MS_BIND MS_REMOUNT MS_RDONLY)))) + #t)) + (stop #~(lambda args + ;; Normally there are no processes left at this point, so + ;; TARGET can be safely unmounted. + + ;; Make sure PID 1 doesn't keep TARGET busy. + (chdir "/") + + (umount #$target) + #f)) + + ;; We need an additional module. + (modules `(((gnu build file-systems) + #:select (check-file-system canonicalize-device-spec)) + ,@%default-modules)) + (imported-modules `((gnu build file-systems) + ,@%default-imported-modules)))))) + (define file-system-service-type ;; TODO(?): Make this an extensible service that takes objects ;; and returns a list of . - (dmd-service-type - 'file-system - (lambda (file-system) - (let ((target (file-system-mount-point file-system)) - (device (file-system-device file-system)) - (type (file-system-type file-system)) - (title (file-system-title file-system)) - (check? (file-system-check? file-system)) - (create? (file-system-create-mount-point? file-system)) - (dependencies (file-system-dependencies file-system))) - (dmd-service - (provision (list (file-system->dmd-service-name file-system))) - (requirement `(root-file-system - ,@(map dependency->dmd-service-name dependencies))) - (documentation "Check, mount, and unmount the given file system.") - (start #~(lambda args - ;; FIXME: Use or factorize with 'mount-file-system'. - (let ((device (canonicalize-device-spec #$device '#$title)) - (flags #$(mount-flags->bit-mask - (file-system-flags file-system)))) - #$(if create? - #~(mkdir-p #$target) - #~#t) - #$(if check? - #~(begin - ;; Make sure fsck.ext2 & co. can be found. - (setenv "PATH" - (string-append - #$e2fsprogs "/sbin:" - "/run/current-system/profile/sbin:" - (getenv "PATH"))) - (check-file-system device #$type)) - #~#t) - - (mount device #$target #$type flags - #$(file-system-options file-system)) - - ;; For read-only bind mounts, an extra remount is needed, - ;; as per , which still - ;; applies to Linux 4.0. - (when (and (= MS_BIND (logand flags MS_BIND)) - (= MS_RDONLY (logand flags MS_RDONLY))) - (mount device #$target #$type - (logior MS_BIND MS_REMOUNT MS_RDONLY)))) - #t)) - (stop #~(lambda args - ;; Normally there are no processes left at this point, so - ;; TARGET can be safely unmounted. - - ;; Make sure PID 1 doesn't keep TARGET busy. - (chdir "/") - - (umount #$target) - #f)) - - ;; We need an additional module. - (modules `(((gnu build file-systems) - #:select (check-file-system canonicalize-device-spec)) - ,@%default-modules)) - (imported-modules `((gnu build file-systems) - ,@%default-imported-modules))))))) + (service-type (name 'file-system) + (extensions + (list (service-extension dmd-root-service-type + file-system-dmd-service) + (service-extension fstab-service-type + identity))))) (define* (file-system-service file-system) "Return a service that mounts @var{file-system}, a @code{} diff --git a/gnu/system.scm b/gnu/system.scm index ff981d95a2..2b8821443a 100644 --- a/gnu/system.scm +++ b/gnu/system.scm @@ -299,6 +299,7 @@ a container or that of a \"bare metal\" system." (operating-system-groups os)) (operating-system-skeletons os)) (operating-system-etc-service os) + (service fstab-service-type '()) (session-environment-service (operating-system-environment-variables os)) host-name procs root-fs unmount