[PATCH] start-vm.nix: implement 3-stage init
This uses s6-svscan as stage 2. Right now all that means is reaping zombies -- there are no services for it to supervise. The application being run in the VM (sommelier hello-wayland in this case) is just run as a direct child of init. I felt it didn't belong as a service because it shouldn't be restarted when it terminates. I don't use s6-linux-init for a couple of reasons: - A lot of the reason to use s6-linux-init comes from wanting to do clever things to seamlessly redirect logs from the console to the file system at some point during stage1. For VMs, I think we're better just logging to the console so logs can be managed in one place on the host. - s6-linux-init is a pain with Nix, because s6-linux-init-maker needs to be run as root, and it generates stuff like pipes that can't be stored in the Nix store. coreutils is only used for cp-ing stage3 to the right place. When services are implemented, this can be removed and the VMs will have one less dependency. To shutdown, we use reboot instead of poweroff because that's what actually gets crosvm to quit. reboot(RB_POWER_OFF) seems to be interpreted by the kernel as halt for some reason I have failed to determine. It prints the halt message and everything. reboot(RB_HALT_SYSTEM) does exactly the same thing. Maybe it's just something to do with running in a VM. --- I've pushed this to crosvm-demo already, but I'm posting it here for feedback and suggestions, especially from anybody with experience with inits or s6. start-vm.nix | 54 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/start-vm.nix b/start-vm.nix index b8d20007521..1345a5620c6 100644 --- a/start-vm.nix +++ b/start-vm.nix @@ -14,25 +14,57 @@ let DEVTMPFS_MOUNT = yes; }; }; - init = writeShellScript "init" '' - set -xe - ${coreutils}/bin/mkdir /dev/pts /dev/shm - ${utillinux}/bin/mount -t tmpfs none /tmp - ${utillinux}/bin/mount -t devpts -o gid=4,mode=620 none /dev/pts - ${utillinux}/bin/mount -t tmpfs none /dev/shm - export XDG_RUNTIME_DIR=/tmp - ${sommelier}/bin/sommelier ${hello-wayland}/bin/hello-wayland + stage1 = writeScript "stage1" '' + #! ${execline}/bin/execlineb -P + importas -i PATH PATH + export PATH ${lib.makeBinPath + [ s6-linux-init s6-portable-utils s6-linux-utils s6 execline coreutils ]} + ${s6}/bin/s6-setsid -qb -- + umask 022 + if { s6-mount -t tmpfs -o mode=0755 tmpfs /run } + if { s6-mkdir -p /run/service/.s6-svscan } + if { cp ${stage3} /run/service/.s6-svscan/finish } + emptyenv -p + + background { + s6-setsid -- + if { s6-mkdir -p /run/user/0 /dev/pts /dev/shm } + if { s6-mount -t devpts -o gid=4,mode=620 none /dev/pts } + if { s6-mount -t tmpfs none /dev/shm } + if { s6-mount -t proc none /proc } + export XDG_RUNTIME_DIR /run/user/0 + foreground { ${sommelier}/bin/sommelier ${hello-wayland}/bin/hello-wayland } + importas -i ? ? + if { echo STATUS: $? } + s6-svscanctl -6 /run/service + } + + unexport ! + cd /run/service + s6-svscan + ''; + + stage3 = writeScript "stage3" '' + #! ${execline}/bin/execlineb -S0 + foreground { s6-nuke -th } + s6-sleep -m -- 2000 + foreground { s6-nuke -k } + wait { } + s6-linux-init-hpr -fr ''; rootfs = runCommand "rootfs" {} '' - mkdir dev bin tmp + mkdir bin dev proc run tmp ln -s ${dash}/bin/sh bin - (cat ${writeReferencesToFile init}; printf "%s\n" bin dev tmp) | xargs tar -cP --hard-dereference | ${squashfs-tools-ng}/bin/tar2sqfs $out + + (cat ${writeReferencesToFile stage1}; printf "%s\n" bin dev proc run tmp) \ + | xargs tar -cP --owner root:0 --group root:0 --hard-dereference \ + | ${squashfs-tools-ng}/bin/tar2sqfs $out ''; in writeShellScript "crosvm" '' set -x - exec ${crosvm}/bin/crosvm run --wayland-sock=$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY -p init=${init} --root=${rootfs} ${kernel}/bzImage + exec ${crosvm}/bin/crosvm run --wayland-sock=$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY -p init=${stage1} --root=${rootfs} ${kernel}/bzImage '' -- 2.23.0
participants (1)
-
Alyssa Ross