Thank you very much !

This have helped me a lot.

I had to mount /dev and to resort to busybox's switch_root because the one built using execline tools had trouble executing. Despite using executables from the actual root filesystem, it had issue spawing tools at some point in the loop. I guess this is because they are not statically compiled.

One improvement would be to use the kernel commandline to select the modules to load and detect the root filesystem. Right now I just use hard-coded values.

The "modules=" option is added as an environment variable by the kernel so this should do the trick:

    import -d, -s modules modprobe -a ${modules}

The "root=" seems a bit tricker: it is only available through parsing /proc/cmdline. I think something like this will do it:

    backtick -ni ROOTFS {
        pipeline {
            forbacktickx OPT { redirfr -r 0 /proc/cmdline s6-cat }
            import -u OPT
            s6-echo $OPT
        }
        pipeline { s6-grep ^root= }
        s6-cut -d= -f2-
    }
    import -u ROOTFS

    backtick -ni ROOTFSTYPE { blkid -s TYPE -o value $ROOTFS }
    import -u ROOTFSTYPE

I have seen alpine's intit script use KOPT_* variables (like KOPT_root, KOPT_quiet and so on) but I have found no reference to them nor have I found them in the environment of process 1.

Now i will take a look at s6-rc examples scripts.

--

Guillaume.


Le 30/01/2017 à 15:19, Laurent Bercot a écrit :

2) have a very small init script to load the modules, mount the filesystems (/dev, /proc, /sys, /), and finally pivot-chroot into s6-linux-init phase 1. This would be less elegent but it might be easier to set up.

 This. If you need or want an initramfs, you need to comply with the
implicit initramfs contract: when you exec into /sbin/init, it must be
the only process running on your machine, just as if the kernel started
it; and any init system should be able to work, the initramfs should not
tie you to a specific init. So, spawning a supervision tree in the
initramfs is a no-no, because it breaks both aspects.

 You can see an initramfs as a mini-system that you set up to do what
needs to be done *and then tear down* before exec'ing into the real system.
So, do that: load your modules, find your rootfs, pivot-chroot into it,
and start your real system with your init of choosing.

 Ideally, you'd even unmount /proc and /sys (which you likely need during
your initramfs execution) before entering /sbin/init. But obviously
that's not practical since your boot sequence will mount then again
very soon, so the separation between "pre-init" and "post-init" can
be a bit less strict. You can document that the state of your system
at init time is "pristine as if the kernel had directly started init,
except that /proc and /sys are already mounted", for instance, and
that's acceptable. (/dev is not even a question - you should have a
devtmpfs mounted at boot anyway, and mount --move it after your
pivot_root.)

 But "after initramfs, I already have a supervision system and just
need to run the rest of the boot sequence" is not acceptable - if only
because you then need to keep supervision executables in RAM, and a
component of your pivoted initramfs in your PATH.

 Just make initramfs as transparent as possible, it's a lot cleaner.

 Oh, by the way, pivot_root works with initrd, but not initramfs: see
https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
so you can use busybox/toybox's switch_root instead, or you can do the
switch_root by hand.

 I have a skeleton /init here that only needs in your initramfs:
 - empty /dev, /proc, /rootfs and /sys directories. OK if the kernel
mounts devtmpfs at boot (which it should).
 - a /sbin directory with a "mdev" static binary inside. (busybox with
only mdev selected will still be 100ish kB, that's unfortunately normal.)
 - a /command directory with static cd, execlineb, export, foreground,
if, redirfd, s6-echo and s6-mount binaries inside. Also "define" for the
skeleton but you'd replace it with something else for your rootfs detection.
 - whatever else you need to do your job - you could add modutils to your
busybox build, for instance, if you want to load modules. You may want
a /etc/mdev.conf depending on the devices you're expecting to detect.
- also execline, s6-portable-utils and s6-linux-utils binaries accessible
in the /command directory of your real root filesystem.

 You can get it at http://pastebin.com/KZfdETy5
 My gzipped initramfs image made with that is about 104kB, for x86_64.

 HTH,

--
 Laurent


Reply via email to