Hi guix-developers and users, Here are some notes I made about how to get `/` on ZFS, maybe someone else can think about it.
------- Most importantly, it seems for this style we need to consider first `/boot` ***not*** on ZFS, and have `/` on ZFS. I presume grub has some way to read ZFS pools in order to get at the `/boot` if `/boot` is on ZFS, since `/`-on-ZFS for Ubuntu is able to put even `/boot` on ZFS, however note that even there the `/boot` is on a different pool from the `/`. When this works (*cough*) it should be possible to create a ZFS pool (with `mountpoint=legacy`) from a ZFS-enabled boot of Guix, then create a `configuration.scm` that we would then `sudo guix system init` onto a temporary mountpoint. I would strongly suggest putting `/boot` elsewhere though. Here are a bunch of things we need for `/` on ZFS: * ZFS module installing into `initrd`. * ZFS module loading while in `initrd` before the pivot to the "real" `/`. * ZFS `import` of the pool containing `/` mount. ## `initrd` module installation We need a facility to add modules to the `initrd` that are not part of the kernel. Currently `raw-initrd`/`base-initrd` will only get `.ko` files from the given `linux` package. We need to modify the `initrd` interface to add say a `#:module-packages` list of packages whose `.ko` files we will also add to the `initrd`. This translates to modifying `flat-linux-module-directory` in `gnu/system/linux-initrd.scm` to additionally accept a list of packages all of whose `.ko` and/or `.ko.gz` files will be added to the module directory. Then somewhere over in `raw-initrd` we would: (define kodir (flat-linux-module-directory linux linux-modules module-packages)) We also need an extensible service type that will eventually lead to adding new entries in the `#:module-packages`. We need a "root" `initrd` extensible service type that will construct the `initrd` via the `operating-system-initrd` field. This service type will accept additional arguments to pass to the `initrd` function. Then the `initrd-kernel-loadable-module-service-type` would accept lists of package specifications, then provide a `#:module-packages` argument to the root `initrd` service type. Rough sketch: (define initrd-arguments-service-type (service-type #;...)) (define initrd-kernel-loadable-module-service-type (service-type (name 'initrd-kernel-loadable-module-service-type) (extensions (list (service-extension initrd-arguments-service-type (lambda (module-packages) (if (null? module-packages) '() (list #:module-packages module-packages)))))) (compose concatenate) (extend append) (default-value '()))) ## `initrd` module explicit loading Normally modules are loaded "as needed" but ZFS needs to be explicitly loaded. The `base-initrd` already accepts a list of `linux-modules` to load, we just need some way to hook into adding `#:linux-modules`. This probably means modifying how `operating-system-initrd-file` in `(gnu system)` works (which would probably be needed by the `initrd-arguments-service-type` anyway). We could try hooking into the currently-deprecated `extra-modules` instead, here's a sketch: (define initrd-kernel-module-loader-service-type (service-type (name 'initrd-kernel-module-loader-service-type) (extensions (list (service-extension initrd-arguments-service-type (lambda (modules) (if (null? modules) '() (list #:extra-modules modules)))))) (compose concatenate) (extend append) (default-value '()))) ## `initrd` additional pre-mount actions Before a `/` on ZFS can be mounted, ZFS has to be told to scan for the ZFS pool containing the `/`. We could add yet another argument to `raw-initrd`/`base-initrd`, `#:premount-actions`, a list of gexpressions. Then the `#:pre-mount` argument to `boot-system` would become something like: #:pre-mount (lambda () (and #$@device-mapping-commands #$@premount-actions)) As usual a service type can be created which extends `initrd-arguments-service-type`. For root-on-ZFS specifically we would need to know the root pool and execute something like this: #~(begin (invoke/quiet #$(file-append zfs/static "/sbin/zpool") "-a" "-N" #$root-pool)) Then, "normal" root specification would be done, with the root pool name given as the device name of the `/` mountpoint, and with the ZFS mountpoint set to `legacy`.