├── .gitignore ├── demo ├── boot.gif ├── zfs.gif ├── quiz-tmux.gif ├── zfs-test.gif ├── zfs.cast ├── zfs-test.cast ├── boot.cast └── quiz-tmux.cast ├── profile ├── error │ ├── init │ └── setup ├── zfs │ └── init ├── memdev │ ├── etc │ │ └── udev │ │ │ └── rules.d │ │ │ └── 99-quiz-memdev.rules │ └── init ├── ztest │ └── local │ │ └── bin │ │ ├── sudo │ │ └── id └── blockdev │ ├── etc │ └── udev │ │ └── rules.d │ │ └── 99-quiz-blockdev.rules │ └── setup ├── rc ├── bashrc ├── raw │ ├── vars │ └── run └── tmux │ ├── vars │ ├── tmux.conf │ ├── run │ └── main ├── quiz-config ├── init ├── init1 └── init2 ├── quiz-root ├── quiz-test ├── quiz-zfs ├── quiz-cleanup ├── quiz-lib ├── quiz ├── README.md ├── quiz-kernel └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | quiz.cfg 2 | build 3 | system 4 | -------------------------------------------------------------------------------- /demo/boot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robn/quiz/HEAD/demo/boot.gif -------------------------------------------------------------------------------- /demo/zfs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robn/quiz/HEAD/demo/zfs.gif -------------------------------------------------------------------------------- /demo/quiz-tmux.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robn/quiz/HEAD/demo/quiz-tmux.gif -------------------------------------------------------------------------------- /demo/zfs-test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robn/quiz/HEAD/demo/zfs-test.gif -------------------------------------------------------------------------------- /profile/error/init: -------------------------------------------------------------------------------- 1 | # sourced by init2 2 | 3 | for d in /.quiz/dm/* ; do 4 | bd=$(basename $d) 5 | dmsetup create $bd < $d 6 | done 7 | 8 | # vim: ft=bash 9 | -------------------------------------------------------------------------------- /profile/zfs/init: -------------------------------------------------------------------------------- 1 | # sourced by init2 2 | 3 | # clean out /etc/zfs from previous runs 4 | rm -rf /etc/zfs 5 | mkdir /etc/zfs 6 | 7 | # load modules 8 | modprobe zfs 9 | 10 | # vim: ft=bash 11 | -------------------------------------------------------------------------------- /profile/memdev/etc/udev/rules.d/99-quiz-memdev.rules: -------------------------------------------------------------------------------- 1 | SUBSYSTEM=="block", KERNEL=="loop[0-9]*", ENV{DEVTYPE}=="disk", PROGRAM="/usr/bin/grep -sq quizm /sys$env{DEVPATH}/loop/backing_file", SYMLINK+="quizm%n" 2 | -------------------------------------------------------------------------------- /profile/ztest/local/bin/sudo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | OPTIND=1 4 | while getopts "SEu:n" opt ; do true ; done 5 | shift $(expr $OPTIND - 1) 6 | 7 | if [[ $# = 0 ]] ; then 8 | exit 1 9 | fi 10 | 11 | exec env QUIZ_SUDO=1 "$@" 12 | 13 | # vim: ft=bash 14 | -------------------------------------------------------------------------------- /profile/blockdev/etc/udev/rules.d/99-quiz-blockdev.rules: -------------------------------------------------------------------------------- 1 | SUBSYSTEM=="block", KERNEL=="vd*[!0-9]", ATTRS{serial}=="quizb*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="$env{ID_SERIAL}" 2 | SUBSYSTEM=="block", KERNEL=="vd*[0-9]", ATTRS{serial}=="quizb*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="$env{ID_SERIAL}p%n" 3 | -------------------------------------------------------------------------------- /profile/memdev/init: -------------------------------------------------------------------------------- 1 | # sourced by init2 2 | 3 | QUIZ_MEMDEV_COUNT=${QUIZ_MEMDEV_COUNT:-2} 4 | QUIZ_MEMDEV_SIZE=${QUIZ_MEMDEV_SIZE:-100M} 5 | 6 | for n in $(seq 0 $(($QUIZ_MEMDEV_COUNT - 1))) ; do 7 | fallocate -l $QUIZ_MEMDEV_SIZE /tmp/quizm$n 8 | d=$(losetup --show -f /tmp/quizm$n) 9 | 10 | echo "quiz: memdev: created quizm$n" >> /dev/kmsg 11 | done 12 | 13 | # vim: ft=bash 14 | -------------------------------------------------------------------------------- /rc/bashrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | source /etc/bash.bashrc 11 | export PS1='quiz# ' 12 | 13 | # vim: ft=bash 14 | -------------------------------------------------------------------------------- /rc/raw/vars: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MPL-2.0 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | # Copyright (c) 2023-2025, Rob Norris 8 | 9 | # when enabled, hypervisor will pass signals through to the guess 10 | # when disabled, hypervisor will handle signals itself 11 | _quiz_rc_signals=on 12 | 13 | # vim: ft=bash 14 | -------------------------------------------------------------------------------- /rc/tmux/vars: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MPL-2.0 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | # Copyright (c) 2023-2025, Rob Norris 8 | 9 | # when enabled, hypervisor will pass signals through to the guess 10 | # when disabled, hypervisor will handle signals itself 11 | _quiz_rc_signals=off 12 | 13 | # vim: ft=bash 14 | -------------------------------------------------------------------------------- /profile/error/setup: -------------------------------------------------------------------------------- 1 | # sourced by quiz 2 | 3 | # depends: blockdev 4 | 5 | endb=$(( ($(numfmt --from=iec $QUIZ_BLOCKDEV_SIZE)-42991616)/512 )) 6 | 7 | rm -rf $RUNDIR/system/init/.quiz/dm 8 | mkdir -p $RUNDIR/system/init/.quiz/dm 9 | for n in $(seq $QUIZ_BLOCKDEV_COUNT) ; do 10 | trace "error: creating erroring dm for blockdev$n" 11 | cat > $RUNDIR/system/init/.quiz/dm/blockdev$n < 9 | 10 | # "raw" rc. just the kernel and program output, all in one, good for piping and 11 | # redirecting. 12 | 13 | # In order for signals to be delivered, we need to run the program in a pty. 14 | # Amazingly, I couldn't find a single simple program that would allocate one 15 | # and run the program. Turns out that `script` is pretty close though, if we 16 | # just dump its "log" elsewhere. Maybe that's the "single simple program" after 17 | # all. 18 | exec script -q -e \ 19 | -c '/bin/sh -- /.quiz/run' \ 20 | /dev/null 21 | 22 | # vim: ft=sh 23 | -------------------------------------------------------------------------------- /rc/tmux/tmux.conf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MPL-2.0 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | # Copyright (c) 2023-2025, Rob Norris 8 | 9 | # basic colours and status layout here 10 | set -g status-style 'bg=color52,fg=white' 11 | set -g status-left '[🧩quiz] ' 12 | 13 | %if "#{==:$QUIZ_PROFILES,}" 14 | set -g status-right " [💽 $QUIZ_KERNEL_VERSION $QUIZ_ARCH]" 15 | %else 16 | set -g status-right " [🪪 $QUIZ_PROFILES] [💽 $QUIZ_KERNEL_VERSION $QUIZ_ARCH]" 17 | %endif 18 | 19 | # vi keys. we all make choices, and must live with their consequences 20 | set -g mode-keys vi 21 | set -g status-keys vi 22 | 23 | # redraw status bar often. since we're testing kernel code, and panics and 24 | # crashes will go to the console "under" tmux, overdrawing makes it much less 25 | # confusing 26 | set -g status-interval 1 27 | 28 | # vim: ft=tmux 29 | -------------------------------------------------------------------------------- /rc/tmux/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | # "tmux" rc, for easier interactive use. 11 | # 12 | # we run tmux inside the VM, with two windows: 13 | # 0: kernel output (dmesg) 14 | # 1: actual program run 15 | # 16 | # this script gets tmux launched, with the the windows set up. rc/tmux/main is 17 | # what actually gets run in the "main" window 18 | 19 | # disable kernel output direct to console, so it doesn't scribble all over tmux 20 | # itself. dmesg is then run in the first window to get the log in a more 21 | # contained fashion 22 | dmesg -n 1 23 | 24 | # start tmux. the config file is mostly for styles and colours. we force 25 | # 256-color and unicode support here, because my terminal handles it and in 26 | # 2025, yours should too. 27 | tmux -2u -f /.quiz/rc/tmux.conf \ 28 | new-session -n 'dmesg' dmesg -w \; \ 29 | new-window -n 'run' /.quiz/rc/main \; \ 30 | 31 | # vim: ft=sh 32 | -------------------------------------------------------------------------------- /quiz-config: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MPL-2.0 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # 7 | # Copyright (c) 2023-2025, Rob Norris 8 | 9 | # default config for 'quiz', including generated config 10 | # don't change this, override in quiz.cfg 11 | 12 | # local machine architecture (-a will override) 13 | QUIZ_ARCH=$(uname -m) 14 | 15 | # kernel version to use (-k will override) 16 | QUIZ_KERNEL_VERSION=6.1 17 | 18 | # default run control (-r will override) 19 | QUIZ_RC=auto 20 | 21 | # default profile set (-p will override) 22 | QUIZ_PROFILE="" 23 | 24 | # memory and CPU count 25 | QUIZ_MEM=2G 26 | QUIZ_CPUS=2 27 | 28 | # extra options to be passed to the kernel or qemu 29 | QUIZ_KERNEL_OPTS="" 30 | QUIZ_QEMU_OPTS="" 31 | 32 | # profile: blockdev 33 | QUIZ_BLOCKDEV_COUNT=2 34 | QUIZ_BLOCKDEV_SIZE=100M 35 | 36 | # profile: memdev 37 | QUIZ_MEMDEV_COUNT=2 38 | QUIZ_MEMDEV_SIZE=100M 39 | 40 | # load user config 41 | RUNDIR=$(realpath $(dirname $0)) 42 | if [[ -f $RUNDIR/quiz.cfg ]] ; then 43 | source $RUNDIR/quiz.cfg 44 | fi 45 | 46 | # vim: ft=bash 47 | -------------------------------------------------------------------------------- /rc/tmux/main: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | # "tmux" rc, for easier interactive use. 11 | # 12 | # this script is run inside the "run" window, see rc/tmux/run for more info. 13 | # 14 | # this sets up a couple of quality-of-life improvements for the program run: 15 | # 16 | # - kernel messages are also displayed here, so they appear interleaved with 17 | # the program output, which is extremely useful if you're like me and do 18 | # a lot of print debugging in the kernel (which is like 90% of the reason 19 | # quiz even exists) 20 | # 21 | # - after the program run, waits for the user to do something before detaching 22 | # (and so exiting the VM). the user may want to examine the output before 23 | # exiting, but we also want to preserve the conceit that the program run and 24 | # the VM lifetime is the same. Without this, the run window would close, 25 | # losing the output, and leaving the user on the kernel log window. Instead, 26 | # we tell them where they're at, give them an instruction, and on exit, 27 | # call `tmux detach` to tear down the VM. 28 | 29 | dmesg_pid= 30 | 31 | finish() { 32 | # from this point, all ways out destroy the world 33 | trap 'tmux detach' INT HUP TERM EXIT 34 | 35 | # no more kernel messages after the run; they're still on the log window 36 | if [ -n $dmesg_pid ] ; then 37 | kill -INT $dmesg_pid 38 | fi 39 | 40 | # a nice message 41 | echo 42 | echo 43 | echo "[quiz run finished. Ctrl-C or detach session to exit]" 44 | echo 45 | 46 | # sleep "forever" (68 years or so) 47 | sleep 2147483648 # 68 years or so 48 | 49 | # hello, future 50 | exit 0 51 | } 52 | 53 | # all user shutdowns should go to the finish stage 54 | trap finish INT HUP TERM 55 | 56 | # emit new kernel messages 57 | dmesg -W & dmesg_pid=$! 58 | 59 | # run the user program! 60 | /bin/sh -- /.quiz/run 61 | 62 | # done 63 | finish 64 | 65 | # vim: ft=sh 66 | -------------------------------------------------------------------------------- /init/init1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | # first-stage init; getting the filesystems up, then we bounce into the 11 | # second-stage init in the quiz work dir 12 | 13 | # bring the local dirs in 14 | for dir in init user kernel system ; do 15 | mount -t 9p -o trans=virtio quiz-$dir /mnt/quiz-$dir \ 16 | -oversion=9p2000.L,posixacl,msize=512000,cache=loose 17 | done 18 | 19 | # build the root overlay. this is creating this layering: 20 | # 21 | # tmpfs /mnt/top/upper [rw] 22 | # quiz init dir /mnt/quiz-init [ro] 23 | # quiz user dir /mnt/quiz-user [ro] 24 | # quiz kernel dir /mnt/quiz-kernel [ro] 25 | # quiz system dir /mnt/quiz-system [ro] 26 | # root.ext2 / [ro] 27 | # 28 | # the overlay is then mounted at /mnt/newroot 29 | mount -t tmpfs tmpfs /mnt/top 30 | mkdir /mnt/top/upper /mnt/top/work 31 | mount --bind / /mnt/lower 32 | mount -t overlay overlay -o lowerdir=/mnt/quiz-init:/mnt/quiz-user:/mnt/quiz-kernel:/mnt/quiz-system:/mnt/lower,upperdir=/mnt/top/upper,workdir=/mnt/top/work /mnt/newroot 33 | 34 | # make /mnt/newroot the new /. after the pivot, the original root is on /mnt 35 | pivot_root /mnt/newroot /mnt/newroot/mnt 36 | 37 | # mount kernel filesystems 38 | mount -t proc none /proc 39 | mount -t sysfs none /sys 40 | mount -t devtmpfs none /dev 41 | mkdir /dev/pts 42 | mount -t devpts none /dev/pts 43 | 44 | # unmount the overlay components mounts, no longer needed (the overlay is still 45 | # holding references under the hood; this just removes them from the visible 46 | # filesystem hierarchy. we use --lazy because this seems to be very slightly 47 | # racy and sometimes leaves one or more still mounted; it hardly matters, we're 48 | # just trying to tidy up 49 | umount --lazy /mnt/mnt/lower 50 | umount --lazy /mnt/mnt/top 51 | umount --lazy /mnt/mnt/quiz-system 52 | umount --lazy /mnt/mnt/quiz-kernel 53 | umount --lazy /mnt/mnt/quiz-user 54 | umount --lazy /mnt/mnt/quiz-init 55 | umount --lazy /mnt 56 | 57 | # bounce into the second stage 58 | exec /.quiz/init2 59 | 60 | # vim: ft=sh 61 | -------------------------------------------------------------------------------- /init/init2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | # second-stage init. filesystem is up, now actually boot the system and run 11 | # the user program 12 | 13 | # at least make the prompt look nice 14 | hostname quiz 15 | 16 | # start udev. we need device node support 17 | /lib/systemd/systemd-udevd >> /dev/kmsg 2>&1 & 18 | udevadm trigger -t subsystems 19 | udevadm trigger -t devices 20 | udevadm settle -t 1 21 | 22 | # help out with fancy shell tricks 23 | ln -s /proc/self/fd /dev/fd 24 | 25 | # mount kernel debug filesystems 26 | mount -t tracefs none /sys/kernel/tracing 27 | mount -t debugfs none /sys/kernel/debug 28 | mount -t configfs none /sys/kernel/config 29 | mount -t cgroup2 none /sys/fs/cgroup 30 | mount -t bpf none /sys/fs/bpf 31 | 32 | # mount the host shared dir 33 | mkdir /shared 34 | mount -t 9p -o trans=virtio quiz-shared /shared \ 35 | -oversion=9p2000.L,posixacl,msize=512000,cache=mmap 36 | 37 | # 38 | # set the terminal size correctly. 39 | # 40 | # we're on an emulated serial port, which can't send SIGWINCH. we know though 41 | # that there's almost certainly a vt100 on the other end of it, so we can ask 42 | # it to help us out. 43 | # 44 | # here, we switch to raw input mode, and send: 45 | # 46 | # \e7 DECSC save cursor (vt100) 47 | # \e[999;999H CUP move cursor to 999,999 48 | # \e[6n DSR report cursor position 49 | # \e8 DECRC restore cursor (vt100) 50 | # 51 | # the terminal responds to DSR by "typing" (_not_ stdin): 52 | # 53 | # \e[;R 54 | # 55 | # note that the terminal does not "type" an enter, thus the need for raw input 56 | # mode. the lack of a newline means that most line-based programs will block. 57 | # but, sed in unbuffered mode will read the minimum required to run the 58 | # program. 59 | # 60 | # so we run sed to match everything up to the R, then convert it into a stty 61 | # command that will set the rows and columns. finally, we reset the terminal, 62 | # and execute the command we built. and now the terminal is properly-sized. 63 | # phew. 64 | # 65 | saveterm="$(stty -g)" 66 | stty raw 67 | stty -echo -icanon min 0 time 1 68 | echo -n '\e7\e[999;999H\e[6n\e8' 69 | resize=$(sed -nu '/.*R/ s/[^0-9;]//g ; s/\([0-9]*\);\([0-9]*\)/stty rows \1 cols \2/ p') 70 | stty "$saveterm" 71 | eval "$resize" 72 | 73 | # get quiz envvars into future shells 74 | ln -sf /.quiz/env /etc/profile.d/quiz.sh 75 | 76 | # if any profiles need work, boot them up 77 | if [ -r /.quiz/init.profile ] ; then 78 | . /.quiz/init.profile 79 | fi 80 | 81 | # start a "real" init and hand control to rc 82 | exec tini -sg -- /bin/sh -l -- /.quiz/rc/run 83 | 84 | # vim: ft=sh 85 | -------------------------------------------------------------------------------- /quiz-root: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | set -uo pipefail 11 | 12 | usage() { 13 | cat < 17 | architecture to create root for 18 | EOF 19 | exit 1 20 | } 21 | 22 | trace() { 23 | local STAMP=$(date +%Y%m%d-%H:%M:%S) 24 | echo "[quiz-root] $STAMP $@" >&2 25 | } 26 | 27 | fail() { 28 | local TEXT=${@:-} 29 | if [[ -z $TEXT ]] ; then 30 | TEXT="[${BASH_SOURCE[0]}:${BASH_LINENO[0]}: $BASH_COMMAND]" 31 | fi 32 | trace "FATAL $TEXT" 33 | exit 1 34 | } 35 | trap fail ERR 36 | 37 | RUNDIR=$(realpath $(dirname $0)) 38 | source $RUNDIR/quiz-config 39 | source $RUNDIR/quiz-lib 40 | 41 | opt_arch="" 42 | 43 | OPTIND=1 44 | while getopts "a:h" opt 45 | do 46 | case "$opt" in 47 | 'a') opt_arch=$OPTARG ;; 48 | 'h') usage ;; 49 | *) exit 1 ;; 50 | esac 51 | done 52 | shift $(expr $OPTIND - 1) 53 | 54 | quiz_arch_vars ${opt_arch:-$QUIZ_ARCH} 55 | quiz_debian_vars 56 | 57 | trace "building root image" 58 | 59 | # XXX this lists should be source from somewhere else -- robn, 2025-01-10 60 | quiz_extras=util-linux-extra,tini,udev,coreutils,procps,kmod,gdisk,dmsetup,tmux,cryptsetup,less 61 | zfs_extras=libtirpc3,libjemalloc2,libasan8 62 | zfstest_extras=ksh,bc,bzip2,cpio,file,acl,sysstat,samba-common-bin,openssl,pamtester,pax,iputils-ping,python3-minimal,rsync,openssh-client,binutils,attr,nfs-kernel-server,lsscsi,parted,linux-base,sudo,xxhash 63 | debug_extras=jq,gdb,strace,bpftrace,linux-perf,xxd,blktrace,mdadm,e2fsprogs,xfsprogs,time,mbuffer,socat,cgroup-tools 64 | 65 | # XXX add things back in the can't be in the default lists because they're 66 | # not installable from debian unstable right now. this is all a mess, as 67 | # you see -- robn, 2025-01-10 68 | if [[ $_quiz_debian_release != "unstable" ]] ; then 69 | zfstest_extras="$zfstest_extras,fio" 70 | fi 71 | 72 | image_basefile=$_quiz_debian_release.$_quiz_debian_arch 73 | 74 | mmdebstrap \ 75 | --mode=unshare \ 76 | --format=ext2 \ 77 | --arch=$_quiz_debian_arch \ 78 | --variant=minbase \ 79 | --include=$quiz_extras,$zfs_extras,$zfstest_extras,$debug_extras \ 80 | --customize-hook='install -m 755 init/init1 "$1"/sbin/init' \ 81 | --customize-hook='mkdir "$1"/mnt/quiz-init' \ 82 | --customize-hook='mkdir "$1"/mnt/quiz-user' \ 83 | --customize-hook='mkdir "$1"/mnt/quiz-kernel' \ 84 | --customize-hook='mkdir "$1"/mnt/quiz-system' \ 85 | --customize-hook='mkdir "$1"/mnt/lower "$1"/mnt/top "$1"/mnt/newroot' \ 86 | $_quiz_debian_release $RUNDIR/system/$image_basefile.new.ext2 "$_quiz_debian_mirror" 87 | mv -vf $RUNDIR/system/$image_basefile.new.ext2 $RUNDIR/system/$image_basefile.ext2 88 | 89 | trace "done" 90 | 91 | # vim: ft=bash 92 | -------------------------------------------------------------------------------- /quiz-test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | # 11 | # This is a small test suite for some of quiz's library functions, which 12 | # are often fiddly. 13 | # 14 | 15 | set -euo pipefail 16 | 17 | trace() { 18 | local STAMP=$(date +%Y%m%d-%H:%M:%S) 19 | echo "[quiz-test] $STAMP $@" >&2 20 | } 21 | 22 | fail() { 23 | trace "FATAL $@" 24 | exit 1 25 | } 26 | trap fail ERR 27 | 28 | RUNDIR=$(realpath $(dirname $0)) 29 | source $RUNDIR/quiz-config 30 | source $RUNDIR/quiz-lib 31 | 32 | function _quiz_test_check () { 33 | if [[ $2 != $3 ]] ; then 34 | err+=("$(printf "%6s: %-25s %-25s" $1 "expected: [$2]" "got: [$3]")") 35 | fi 36 | return 0 37 | } 38 | 39 | function quiz_test_kernel_vars () { 40 | cat <<-EOT | \ 41 | #input ver srcver type maj min patch typpatch 42 | 6.1 6.1.0 6.1 release 6 1 0 43 | 6.1.0 6.1.0 6.1 release 6 1 0 44 | 6.1-rc1 6.1.0-rc1 6.1-rc1 rc 6 1 0 1 45 | 6.1.0-rc1 6.1.0-rc1 6.1-rc1 rc 6 1 0 1 46 | 6.1.1 6.1.1 6.1.1 release 6 1 1 47 | 6.1.2 6.1.2 6.1.2 release 6 1 2 48 | 5.10.217 5.10.217 5.10.217 release 5 10 217 49 | 6.10-rc1 6.10.0-rc1 6.10-rc1 rc 6 10 0 1 50 | 6.10.0-rc1 6.10.0-rc1 6.10-rc1 rc 6 10 0 1 51 | next-20250721 0.0.0-next-20250721 0.0-next-20250721 next 0 0 0 20250721 52 | 6.16.0-next-20250618 6.16.0-next-20250618 6.16-next-20250618 next 6 16 0 20250618 53 | EOT 54 | grep -v '^#' | \ 55 | while read kin kver ksrcver ktype kmajor kminor kpatch ktypepatch; do 56 | quiz_kernel_vars $kin || true 57 | local err=() 58 | _quiz_test_check "ver" "$kver" "$_quiz_kver" 59 | _quiz_test_check "srcver" "$ksrcver" "$_quiz_ksrcver" 60 | _quiz_test_check "type" "$ktype" "$_quiz_ktype" 61 | _quiz_test_check "major" "$kmajor" "$_quiz_kmajor" 62 | _quiz_test_check "minor" "$kminor" "$_quiz_kminor" 63 | _quiz_test_check "patch" "$kpatch" "$_quiz_kpatch" 64 | _quiz_test_check "typpatch" "$ktypepatch" "$_quiz_ktype_patch" 65 | if [[ ${#err[*]} -eq 0 ]] ; then 66 | echo "$kin: PASS" 67 | else 68 | echo "$kin: FAIL" 69 | local _ifs="$IFS" 70 | IFS=$'\n' 71 | echo "${err[*]}" 72 | IFS="$_ifs" 73 | fi 74 | done 75 | } 76 | 77 | opt_verbose="" 78 | 79 | OPTIND=1 80 | while getopts "v" opt 81 | do 82 | case "$opt" in 83 | 'v') opt_verbose="$opt_verbose$opt" ;; 84 | *) exit 1 ;; 85 | esac 86 | done 87 | shift $(expr $OPTIND - 1) 88 | 89 | if [[ ${#opt_verbose} -ge 1 ]] ; then 90 | export QUIZ_DEBUG_VARS=1 91 | fi 92 | if [[ ${#opt_verbose} -ge 2 ]] ; then 93 | export QUIZ_DEBUG_VARS_PARSE=1 94 | fi 95 | 96 | quiz_test_kernel_vars 97 | 98 | # vim: ft=bash 99 | -------------------------------------------------------------------------------- /quiz-zfs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | set -uo pipefail 11 | 12 | usage() { 13 | cat < [program args...] 16 | 17 | options: 18 | -k kernel to use for this run 19 | -a architecture to build for 20 | -h this help 21 | EOF 22 | exit 1 23 | } 24 | 25 | trace() { 26 | local STAMP=$(date +%Y%m%d-%H:%M:%S) 27 | echo "[quiz-zfs] $STAMP $@" >&2 28 | } 29 | 30 | fail() { 31 | local TEXT=${@:-} 32 | if [[ -z $TEXT ]] ; then 33 | TEXT="[${BASH_SOURCE[0]}:${BASH_LINENO[0]}: $BASH_COMMAND]" 34 | fi 35 | trace "FATAL $TEXT" 36 | exit 1 37 | } 38 | trap fail ERR 39 | 40 | RUNDIR=$(realpath $(dirname $0)) 41 | source $RUNDIR/quiz-config 42 | source $RUNDIR/quiz-lib 43 | 44 | opt_arch="" 45 | opt_kernel="" 46 | 47 | # take the default kernel version from the last configured version 48 | if [[ -f config.log ]] ; then 49 | opt_kernel=$( ( grep ^LINUX_VERSION= config.log || true ) | cut -f2 -d"'" ) 50 | fi 51 | 52 | OPTIND=1 53 | while getopts "a:k:h" opt 54 | do 55 | case "$opt" in 56 | 'a') opt_arch=$OPTARG ;; 57 | 'k') opt_kernel=$OPTARG ;; 58 | 'h') usage ;; 59 | *) exit 1 ;; 60 | esac 61 | done 62 | shift $(expr $OPTIND - 1) 63 | 64 | if [[ $# -lt 1 ]] ; then 65 | usage 66 | fi 67 | 68 | quiz_arch_vars ${opt_arch:-$QUIZ_ARCH} 69 | quiz_kernel_best_available ${opt_kernel:-$QUIZ_KERNEL_VERSION} 70 | 71 | do_configure() { 72 | local cross_opts="" 73 | if [[ -z $_quiz_arch_native ]] ; then 74 | cross_opts=" 75 | --host=$_quiz_arch_prefix 76 | KERNEL_CROSS_COMPILE=${_quiz_arch_prefix}- 77 | KERNEL_ARCH=$_quiz_arch_kernel 78 | " 79 | fi 80 | 81 | # XXX bunch of this needs to go into configure proper, disabling contrib 82 | # and whatnot. installing to /opt/zfs would be preferable, but 83 | # zts-tests.sh is hardcoded to /usr for now -- robn, 2025-01-13 84 | ./configure \ 85 | --config-cache \ 86 | --with-linux=$RUNDIR/system/kernel/$_quiz_arch_kernel/kbuild/$_quiz_kver \ 87 | --prefix=/usr/local \ 88 | --disable-sysvinit \ 89 | --disable-systemd \ 90 | --disable-pam \ 91 | --disable-pyzfs \ 92 | --with-mounthelperdir=/usr/local/sbin \ 93 | --with-dracutdir=/usr/local/lib/dracut \ 94 | --with-udevdir=/usr/local/lib/udev \ 95 | $cross_opts \ 96 | "lt_cv_sys_lib_dlsearch_path_spec=/lib /usr/lib /usr/lib/$_quiz_arch_prefix" \ 97 | "$@" 98 | } 99 | 100 | do_make() { 101 | make "$@" 102 | } 103 | 104 | do_make_install() { 105 | # merged /usr setup 106 | for d in lib lib32 lib64 bin sbin ; do 107 | mkdir -p $RUNDIR/system/work/usr/$d 108 | ln -sf usr/$d $RUNDIR/system/work/$d 109 | done 110 | 111 | kdest=$RUNDIR/system/kernel/$_quiz_arch_kernel 112 | make install \ 113 | INSTALL_MOD_PATH=$kdest \ 114 | DESTDIR=$RUNDIR/system/work \ 115 | "$@" 116 | /sbin/depmod -A -b $kdest $_quiz_kver 117 | } 118 | 119 | case "$1" in 120 | configure) 121 | do_configure "${@:2}" 122 | ;; 123 | make) 124 | if [[ $# -ge 2 && $2 == install ]] ; then 125 | do_make_install "${@:3}" 126 | else 127 | do_make "${@:2}" 128 | fi 129 | ;; 130 | *) 131 | usage 132 | ;; 133 | esac 134 | 135 | # vim: ft=bash 136 | -------------------------------------------------------------------------------- /quiz-cleanup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | set -uo pipefail 11 | 12 | usage() { 13 | cat <&2 31 | } 32 | 33 | fail() { 34 | local TEXT=${@:-} 35 | if [[ -z $TEXT ]] ; then 36 | TEXT="[${BASH_SOURCE[0]}:${BASH_LINENO[0]}: $BASH_COMMAND]" 37 | fi 38 | trace "FATAL $TEXT" 39 | exit 1 40 | } 41 | trap fail ERR 42 | 43 | RUNDIR=$(realpath $(dirname $0)) 44 | source $RUNDIR/quiz-config 45 | source $RUNDIR/quiz-lib 46 | 47 | opt_kernel="" 48 | opt_old_kernels="" 49 | opt_delete="" 50 | 51 | OPTIND=1 52 | while getopts "k:KDh" opt 53 | do 54 | case "$opt" in 55 | 'k') opt_kernel=$OPTARG ;; 56 | 'K') opt_old_kernels=1 ;; 57 | 'D') opt_delete=1 ;; 58 | 'h') usage ;; 59 | *) exit 1 ;; 60 | esac 61 | done 62 | shift $(expr $OPTIND - 1) 63 | 64 | cd $RUNDIR 65 | 66 | if [[ -n $opt_kernel && -n $opt_old_kernels ]] ; then 67 | fail "invalid kernel version options; can't use -k and -K together" 68 | fi 69 | 70 | function find_all_kernels () { 71 | ( 72 | ls system/bzImage-* | grep -E -- '-[0-9]+\.[0-9]+\.[0-9]+$' | cut -f2 -d- 73 | ls system/work/lib/modules | grep -E -- '^[0-9]+\.[0-9]+\.[0-9]+$' 74 | ls -d system/work/usr/local/src/*/* | grep -oE -- '/[0-9]+\.[0-9]+\.[0-9]+$' | cut -f2 -d/ 75 | ls -d build/kernel/linux-* | grep -oE -- '[0-9]+\.[0-9]+\.[0-9]+' 76 | ) | sort -V | uniq | tac 77 | } 78 | 79 | all_kernels=$(find_all_kernels) 80 | cleanup_kernels="" 81 | keep_kernels="" 82 | 83 | if [[ -n $opt_kernel ]] ; then 84 | for k in $all_kernels ; do 85 | if [[ $k == $opt_kernel ]] ; then 86 | cleanup_kernels=$opt_kernel 87 | fi 88 | done 89 | fi 90 | 91 | if [[ -z $cleanup_kernels ]] ; then 92 | min_kernels="" 93 | if [[ -n $opt_kernel ]] ; then 94 | min_kernels=$opt_kernel 95 | else 96 | min_kernels=$(echo $all_kernels | xargs -n1 echo | cut -f1-2 -d. | sort -V | uniq ) 97 | fi 98 | for kmin in $min_kernels ; do 99 | first=0 100 | for k in $all_kernels ; do 101 | if [[ $(echo $k | cut -f1-2 -d.) == $kmin ]] ; then 102 | if [[ $first -eq 0 ]] ; then 103 | keep_kernels="$keep_kernels $k" 104 | first=1 105 | else 106 | cleanup_kernels="$cleanup_kernels $k" 107 | fi 108 | fi 109 | done 110 | done 111 | fi 112 | 113 | if [[ -z $cleanup_kernels ]] ; then 114 | fail "no matching kernels found, nothing to do!" 115 | fi 116 | 117 | trace "will cleanup kernels:$cleanup_kernels" 118 | if [[ -n $keep_kernels ]] ; then 119 | trace "keeping kernels:$keep_kernels" 120 | fi 121 | 122 | for k in $cleanup_kernels ; do 123 | ( 124 | ls system/bzImage-$k || true 125 | ls -d system/work/usr/lib/modules/$k || true 126 | ls -d system/work/usr/local/src/*/$k || true 127 | ls -d build/kernel/linux-$k* || true 128 | ) 2>/dev/null | sort | while read d ; do 129 | if [[ -n $opt_delete ]] ; then 130 | trace "deleting: $d" 131 | rm -rf $d 132 | else 133 | trace "would delete: $d" 134 | fi 135 | done 136 | done 137 | 138 | # vim: ft=bash 139 | -------------------------------------------------------------------------------- /quiz-lib: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | # 11 | # Linux source version numbers (the tarball version) don't always match their 12 | # installed version number (module dir version, uname -a output), eg: 13 | # 14 | # source installed 15 | # 6.9-rc1 6.9.0-rc1 16 | # 6.9 6.9.0 17 | # 6.9.1 6.9.1 18 | # 19 | # we allow any form. internally, we'll set up variables for the "version" 20 | # (installed) and "source version" (source), and also vars for all the pieces 21 | # 22 | 23 | # separate function for the pre-cooked parse; used by quiz-kernel 24 | # to request "latest in series" 25 | function _quiz_kernel_vars () { 26 | local kver=$1 27 | 28 | _quiz_kver="" 29 | _quiz_ksrcver="" 30 | _quiz_kmajor="" 31 | _quiz_kminor="" 32 | _quiz_kpatch="" 33 | _quiz_ktype="" 34 | _quiz_ktype_patch="" 35 | 36 | if [[ ${kver%%-*} = "next" ]] ; then 37 | _quiz_kmajor=0 38 | _quiz_kminor=0 39 | _quiz_kpatch=0 40 | _quiz_ktype=next 41 | _quiz_ktype_patch=${kver##next-} 42 | else 43 | shopt -s lastpipe 44 | eval $(echo $kver | perl -nE ' 45 | ($maj, $min, $pat, $ty, $typat) = m/ 46 | ^ 47 | ([1-9][0-9]*) # major 48 | \. # dot sep 49 | (0|[1-9][0-9]*) # minor 50 | (?:\.(0|[1-9][0-9]*))? # patch 1+, optional 51 | (?:-(rc|next)-?([1-9][0-9]*))? # type & typepatch 52 | $ 53 | /gx; 54 | print <<~EOF; 55 | _quiz_kmajor=$maj 56 | _quiz_kminor=$min 57 | _quiz_kpatch=$pat 58 | _quiz_ktype=$ty 59 | _quiz_ktype_patch=$typat 60 | EOF 61 | ') 62 | fi 63 | 64 | if [[ -n "${QUIZ_DEBUG_VARS_PARSE:-}" ]] ; then 65 | cat 2>&1 <&1 <&1 <&1 < 9 | 10 | set -uo pipefail 11 | 12 | usage() { 13 | cat < 19 | list of profiles to include in this run 20 | -a 21 | architecture to use for this run 22 | -k 23 | kernel to use for this run 24 | -r 25 | use the given runcontrol (default: auto) 26 | -S drop into shell after run script completes 27 | -h this help 28 | EOF 29 | exit 1 30 | } 31 | 32 | trace() { 33 | local STAMP=$(date +%Y%m%d-%H:%M:%S) 34 | echo "[quiz] $STAMP $@" >&2 35 | } 36 | 37 | fail() { 38 | local TEXT=${@:-} 39 | if [[ -z $TEXT ]] ; then 40 | TEXT="[${BASH_SOURCE[0]}:${BASH_LINENO[0]}: $BASH_COMMAND]" 41 | fi 42 | trace "FATAL $TEXT" 43 | exit 1 44 | } 45 | trap fail ERR 46 | 47 | RUNDIR=$(realpath $(dirname $0)) 48 | source $RUNDIR/quiz-config 49 | source $RUNDIR/quiz-lib 50 | 51 | opt_arch="" 52 | opt_kernel="" 53 | opt_profile="" 54 | opt_shell="" 55 | opt_rc="" 56 | 57 | OPTIND=1 58 | while getopts "a:k:p:Sr:h" opt 59 | do 60 | case "$opt" in 61 | 'a') opt_arch=$OPTARG ;; 62 | 'k') opt_kernel=$OPTARG ;; 63 | 'p') opt_profile=$OPTARG ;; 64 | 'S') opt_shell=1 ;; 65 | 'r') opt_rc=$OPTARG ;; 66 | 'h') usage ;; 67 | *) exit 1 ;; 68 | esac 69 | done 70 | shift $(expr $OPTIND - 1) 71 | 72 | quiz_arch_vars ${opt_arch:-$QUIZ_ARCH} 73 | quiz_debian_vars 74 | quiz_kernel_best_available ${opt_kernel:-$QUIZ_KERNEL_VERSION} 75 | 76 | # create init dir and install second stage 77 | rm -rf $RUNDIR/system/init 78 | mkdir -p $RUNDIR/system/init/.quiz 79 | install -m 755 init/init2 $RUNDIR/system/init/.quiz/init2 80 | 81 | # rc selection 82 | rc=${opt_rc:-$QUIZ_RC} 83 | if [[ -z $rc || $rc = 'auto' ]] ; then 84 | rc=raw 85 | if [[ -t 1 ]] ; then 86 | rc=tmux 87 | fi 88 | fi 89 | if [[ ! -d $RUNDIR/rc/$rc ]] ; then 90 | fail "unknown rc: $rc" 91 | fi 92 | trace "using rc: $rc" 93 | if [[ -r $RUNDIR/rc/$rc/vars ]] ; then 94 | source $RUNDIR/rc/$rc/vars 95 | fi 96 | rsync -a $RUNDIR/rc/$rc/ $RUNDIR/system/init/.quiz/rc 97 | cp $RUNDIR/rc/bashrc $RUNDIR/system/init/.quiz/rc 98 | 99 | # ensure system and user dirs exist 100 | mkdir -p $RUNDIR/system/{work,user,shared} 101 | 102 | # delete profile file insertions from previous runs 103 | # XXX maybe these should be part of .quiz and in the overlay 104 | find profile/*/etc -type f | cut -d/ -f3- | \ 105 | awk "{ print \"$RUNDIR/system/work/\" \$1 }" | \ 106 | xargs rm -f 107 | 108 | # get profiles set up. source the profile setup here, and build a profile init 109 | # to be run right before we exec into the real program 110 | profiles=$(echo ${opt_profile:-$QUIZ_PROFILE} | sed 's/,/ /g' | xargs -n1 | sort | xargs) 111 | if [[ $profiles ]] ; then 112 | for v in ${!QUIZ_@} ; do 113 | echo "$v=${!v@Q}" >> $RUNDIR/system/init/.quiz/init.profile 114 | done 115 | fi 116 | for p in $profiles ; do 117 | if [[ ! -d $RUNDIR/profile/$p ]] ; then 118 | fail "unknown profile: $p" 119 | fi 120 | trace "including profile: $p" 121 | 122 | if [[ -f $RUNDIR/profile/$p/setup ]] ; then 123 | source $RUNDIR/profile/$p/setup 124 | fi 125 | 126 | if [[ -f $RUNDIR/profile/$p/init ]] ; then 127 | echo "echo 'quiz: starting profile init: $p' >> /dev/kmsg" \ 128 | >> $RUNDIR/system/init/.quiz/init.profile 129 | cat $RUNDIR/profile/$p/init >> $RUNDIR/system/init/.quiz/init.profile 130 | fi 131 | 132 | # insert profile-specific files into /etc and /usr/local 133 | # XXX maybe these should be part of .quiz and in the overlay 134 | if [[ -d $RUNDIR/profile/$p/etc ]] ; then 135 | rsync -a $RUNDIR/profile/$p/etc/ $RUNDIR/system/work/etc/ 136 | fi 137 | if [[ -d $RUNDIR/profile/$p/local ]] ; then 138 | rsync -a $RUNDIR/profile/$p/local/ $RUNDIR/system/work/usr/local/ 139 | fi 140 | done 141 | 142 | # set up a run script for init to execute 143 | trace "creating run script" 144 | rm -f $RUNDIR/system/init/.quiz/run 145 | if [[ $# -ne 0 ]] ; then 146 | cat < $RUNDIR/system/init/.quiz/run 147 | echo "quiz: starting user program" >> /dev/kmsg 148 | $@ 149 | EOF 150 | if [[ $opt_shell ]] ; then 151 | cat <> $RUNDIR/system/init/.quiz/run 152 | echo "quiz: user program done, dropping to shell" >> /dev/kmsg 153 | /bin/bash --rcfile /.quiz/rc/bashrc 154 | EOF 155 | fi 156 | else 157 | cat < $RUNDIR/system/init/.quiz/run 158 | echo "quiz: starting shell" >> /dev/kmsg 159 | /bin/bash --rcfile /.quiz/rc/bashrc 160 | EOF 161 | fi 162 | cat <> $RUNDIR/system/init/.quiz/run 163 | # kill kernel output on successful completion, to suppress the panic shutdown 164 | # crash 165 | echo 0 0 0 0 > /proc/sys/kernel/printk 166 | EOF 167 | chmod +x $RUNDIR/system/init/.quiz/run 168 | 169 | # build environment file 170 | cat < $RUNDIR/system/init/.quiz/env 171 | export QUIZ_ARCH=$_quiz_arch 172 | export QUIZ_KERNEL_VERSION=$_quiz_kver 173 | export QUIZ_PROFILES="$profiles" 174 | 175 | #for p in \$QUIZ_PROFILES ; do 176 | # for d in /opt/\$p/bin /opt/\$p/sbin ; do 177 | # if [ -d \$d ] ; then 178 | # PATH="\$d:\$PATH" 179 | # fi 180 | # done 181 | #done 182 | #export PATH 183 | export PATH="\$PATH:/usr/local/sbin:/usr/sbin:/sbin" 184 | EOF 185 | 186 | trace "starting microvm" 187 | 188 | # 189 | # XXX note to self. every time I've tried to change the console type to 190 | # something else to get better support for acting like a true terminal, its 191 | # failed. Ultimately, they all have basically no smarts at all, and are all 192 | # harder to access from the host than stdio (at least in the transient way 193 | # I want to). Don't bother. 194 | # 195 | # The key to every UI pleasantry has been to allocate a pseudo-terminal 196 | # inside and build off of that. I think that SIGWINCH passthrough is the 197 | # only true missing piece at this point, and then all would be well. 198 | # -- robn, 2025-01-09 199 | # 200 | 201 | qemu_bin=qemu-system-$_quiz_arch_qemu 202 | qemu_machine_opts="" 203 | qemu_cpu_opts="" 204 | case "$_quiz_arch_qemu" in 205 | x86_64) 206 | # if the host is x86_64 and KVM is available to us, we can use microvm+cpu accel 207 | if [[ -n $_quiz_arch_native && -w /dev/kvm ]] ; then 208 | qemu_machine_opts="-machine microvm,pit=off,pic=off,rtc=off,isa-serial=off,pcie=on" 209 | qemu_cpu_opts="-cpu host -enable-kvm" 210 | else 211 | qemu_machine_opts="-machine q35" 212 | qemu_cpu_opts="-cpu max" 213 | fi 214 | ;; 215 | aarch64) 216 | qemu_machine_opts="-machine virt" 217 | if [[ -n $_quiz_arch_native && -w /dev/kvm ]] ; then 218 | qemu_cpu_opts="-cpu host -enable-kvm" 219 | else 220 | qemu_cpu_opts="-cpu cortex-a53" 221 | fi 222 | ;; 223 | riscv64) 224 | qemu_machine_opts="-machine virt" 225 | qemu_cpu_opts="-cpu sifive-u54" 226 | ;; 227 | loongarch64) 228 | qemu_machine_opts="-machine virt" 229 | qemu_cpu_opts="-cpu la464" 230 | ;; 231 | ppc64) 232 | qemu_machine_opts="-machine ppce500" 233 | qemu_cpu_opts="-cpu e6500" 234 | ;; 235 | *) 236 | fail "no support for architecture: $_quiz_arch_qemu" 237 | ;; 238 | esac 239 | 240 | qemu_mem=${QUIZ_MEM:-2G} 241 | qemu_cpus=${QUIZ_CPUS:-2} 242 | 243 | $qemu_bin $qemu_machine_opts $qemu_cpu_opts \ 244 | -m $qemu_mem -smp $qemu_cpus \ 245 | -kernel $_quiz_kernel_image \ 246 | -append "console=hvc0 root=/dev/vda ro reboot=t $QUIZ_KERNEL_OPTS" \ 247 | -nodefaults -no-user-config -nographic \ 248 | -chardev stdio,mux=on,signal=${_quiz_rc_signals:-off},id=virtiocon0 \ 249 | -mon chardev=virtiocon0,mode=readline \ 250 | -device virtio-serial-pci \ 251 | -device virtconsole,chardev=virtiocon0 \ 252 | -device virtio-balloon-pci \ 253 | -device pvpanic-pci \ 254 | -drive id=root,file=$RUNDIR/system/$_quiz_debian_release.$_quiz_debian_arch.ext2,format=raw,read-only=on,if=none \ 255 | -device virtio-blk-pci,drive=root,serial=root \ 256 | -fsdev local,id=quiz-init,path=$RUNDIR/system/init,security_model=none,readonly=on \ 257 | -device virtio-9p-pci,fsdev=quiz-init,mount_tag=quiz-init \ 258 | -fsdev local,id=quiz-kernel,path=$RUNDIR/system/kernel/$_quiz_arch_kernel,security_model=none,readonly=on \ 259 | -device virtio-9p-pci,fsdev=quiz-kernel,mount_tag=quiz-kernel \ 260 | -fsdev local,id=quiz-system,path=$RUNDIR/system/work,security_model=none,readonly=on \ 261 | -device virtio-9p-pci,fsdev=quiz-system,mount_tag=quiz-system \ 262 | -fsdev local,id=quiz-user,path=$RUNDIR/system/user,security_model=none,readonly=on \ 263 | -device virtio-9p-pci,fsdev=quiz-user,mount_tag=quiz-user \ 264 | -fsdev local,id=quiz-shared,path=$RUNDIR/system/shared,security_model=none \ 265 | -device virtio-9p-pci,fsdev=quiz-shared,mount_tag=quiz-shared \ 266 | $QUIZ_QEMU_OPTS \ 267 | 268 | trace "done" 269 | 270 | # vim: ft=bash 271 | -------------------------------------------------------------------------------- /demo/zfs.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 80, "height": 25, "timestamp": 1694263841, "env": {"SHELL": "/bin/bash", "TERM": "xterm-kitty"}, "title": "quiz ZFS pool create"} 2 | [0.036392, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m⇡\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 3 | [0.704852, "o", "."] 4 | [0.885899, "o", "/"] 5 | [1.056855, "o", "q"] 6 | [1.159517, "o", "u"] 7 | [1.25287, "o", "i"] 8 | [1.427212, "o", "z"] 9 | [1.550774, "o", " "] 10 | [1.674041, "o", "-"] 11 | [1.86871, "o", "p"] 12 | [1.970036, "o", " "] 13 | [2.132247, "o", "z"] 14 | [2.303145, "o", "f"] 15 | [2.438448, "o", "s"] 16 | [2.53083, "o", ","] 17 | [2.773443, "o", "m"] 18 | [2.832349, "o", "e"] 19 | [2.976159, "o", "m"] 20 | [3.076967, "o", "d"] 21 | [3.178375, "o", "e"] 22 | [3.327297, "o", "v"] 23 | [4.055097, "o", " "] 24 | [4.251249, "o", "'"] 25 | [4.568378, "o", "z"] 26 | [4.689004, "o", "p"] 27 | [4.847578, "o", "o"] 28 | [5.015894, "o", "o"] 29 | [5.194965, "o", "l"] 30 | [5.266851, "o", " "] 31 | [5.325809, "o", "c"] 32 | [5.472538, "o", "r"] 33 | [5.586141, "o", "e"] 34 | [5.749368, "o", "a"] 35 | [5.994277, "o", "t"] 36 | [6.122296, "o", "e"] 37 | [6.254041, "o", " "] 38 | [6.419408, "o", "t"] 39 | [6.676391, "o", "a"] 40 | [6.854425, "o", "n"] 41 | [6.9666, "o", "k"] 42 | [7.148847, "o", " "] 43 | [7.363208, "o", "q"] 44 | [7.474122, "o", "u"] 45 | [7.521919, "o", "i"] 46 | [7.677797, "o", "z"] 47 | [7.855636, "o", "m"] 48 | [8.007415, "o", "0"] 49 | [8.124618, "o", " "] 50 | [8.253526, "o", "q"] 51 | [8.37311, "o", "u"] 52 | [8.420032, "o", "i"] 53 | [8.583022, "o", "z"] 54 | [8.768544, "o", "m"] 55 | [9.008834, "o", "1"] 56 | [9.307246, "o", " "] 57 | [9.788687, "o", "&"] 58 | [9.961592, "o", "&"] 59 | [10.743448, "o", " "] 60 | [11.768979, "o", "z"] 61 | [11.826885, "o", "p"] 62 | [12.012569, "o", "o"] 63 | [12.192333, "o", "o"] 64 | [12.419391, "o", "l"] 65 | [12.550841, "o", " "] 66 | [12.682158, "o", "s"] 67 | [12.877303, "o", "t"] 68 | [13.039967, "o", "a"] 69 | [13.160064, "o", "t"] 70 | [13.278186, "o", "u"] 71 | [13.524063, "o", "s"] 72 | [13.900577, "o", " "] 73 | [14.505677, "o", "&"] 74 | [14.655512, "o", "&"] 75 | [14.789925, "o", " "] 76 | [15.049594, "o", "s"] 77 | [15.143341, "o", "l"] 78 | [15.299501, "o", "e"] 79 | [15.452924, "o", "e"] 80 | [15.558322, "o", "p \r"] 81 | [15.725839, "o", " "] 82 | [15.841647, "o", "5"] 83 | [16.468546, "o", "'"] 84 | [17.484762, "o", "\r\n\u001b[?2004l\r"] 85 | [17.539752, "o", "[quiz] 20230909-22:50:58 including profile: zfs\r\n"] 86 | [17.550816, "o", "[quiz] 20230909-22:50:58 including profile: memdev\r\n"] 87 | [17.616481, "o", "[quiz] 20230909-22:50:58 creating run script\r\n"] 88 | [17.62208, "o", "[quiz] 20230909-22:50:58 starting microvm\r\n"] 89 | [18.553098, "o", "[ 0.316036] brd: module loaded\r\r\n"] 90 | [18.680106, "o", "[ 0.443019] loop: module loaded\r\r\n"] 91 | [18.681942, "o", "[ 0.444823] virtio_blk virtio2: [vda] 1608310 512-byte logical blocks (823 MB/785 MiB)\r\r\n"] 92 | [18.681989, "o", "[ 0.444995] vda: detected capacity change from 0 to 823454720\r\r\n"] 93 | [18.696209, "o", "[ 0.459177] i8042: PNP: No PS/2 controller found.\r\r\n"] 94 | [18.696566, "o", "[ 0.459579] device-mapper: io"] 95 | [18.696584, "o", "ctl: 4.43.0-ioctl (2020-10-01) i"] 96 | [18.696594, "o", "nitialised: dm-d"] 97 | [18.696603, "o", "evel@redhat.com\r"] 98 | [18.696678, "o", "\r\n"] 99 | [18.697023, "o", "[ 0.460066] N"] 100 | [18.697041, "o", "ET: Registered protocol family 1"] 101 | [18.697107, "o", "7\r\r\n"] 102 | [18.697118, "o", "[ 0.460195] 9"] 103 | [18.697171, "o", "pnet: Installing"] 104 | [18.697202, "o", " 9P2000 support\r\r\n"] 105 | [18.698416, "o", "[ 0.461457] NET: Registered p"] 106 | [18.698472, "o", "rotocol family 4"] 107 | [18.698523, "o", "0\r\r\n[ 0.461566] o"] 108 | [18.698562, "o", "profile: using NMI interrupt.\r\r\n"] 109 | [18.6986, "o", "[ 0.461631] IPI shorthand broadcast: enabled\r\r\n"] 110 | [18.698649, "o", "[ 0.461685] AVX2 version of gcm_enc/dec engaged.\r\r\n"] 111 | [18.698684, "o", "[ 0.461733] AES CTR mode by8 optimization enabled\r\r\n"] 112 | [18.701055, "o", "[ 0.464125] sched_clock: Mark"] 113 | [18.7011, "o", "ing stable (460694380, 3420084)->(477733470, -13619006)\r\r\n"] 114 | [18.701224, "o", "[ 0.464299] r"] 115 | [18.701263, "o", "egistered taskstats version 1\r\r\n"] 116 | [18.701297, "o", "[ 0.464354] Loading compiled-in X.509 certificates\r\r\n"] 117 | [18.701798, "o", "[ 0.464875] EXT4-fs (vda): mo"] 118 | [18.701839, "o", "unting ext2 file system using th"] 119 | [18.701885, "o", "e ext4 subsystem\r\r\n"] 120 | [18.702292, "o", "[ 0.465377] EXT4-fs (vda): mo"] 121 | [18.702339, "o", "unted filesystem without journal. Opts: (null)\r\r\n"] 122 | [18.702379, "o", "[ 0.465452] V"] 123 | [18.702427, "o", "FS: Mounted root (ext2 filesystem) readonly on d"] 124 | [18.702461, "o", "evice 254:0.\r\r\n"] 125 | [18.703166, "o", "[ 0.466253] F"] 126 | [18.703203, "o", "reeing unused ke"] 127 | [18.703236, "o", "rnel image (initmem) memory: 2332K\r\r\n"] 128 | [18.71998, "o", "[ 0.482977] Write protecting "] 129 | [18.720066, "o", "the kernel read-only data: 18432k\r\r\n"] 130 | [18.720969, "o", "[ 0.484004] Freeing unused ke"] 131 | [18.720979, "o", "rnel image (text"] 132 | [18.720996, "o", "/rodata gap) memory: 2040K\r\r\n"] 133 | [18.721159, "o", "[ 0.484202] F"] 134 | [18.721166, "o", "reeing unused ke"] 135 | [18.721216, "o", "rnel image (rodata/data gap) memory: 592K\r\r\n"] 136 | [18.721632, "o", "[ 0.484685] x"] 137 | [18.721641, "o", "86/mm: Checked W"] 138 | [18.721696, "o", "+X mappings: passed, no W+X page"] 139 | [18.721731, "o", "s found.\r\r\n[ 0.484810] Run /sbin/init as"] 140 | [18.721775, "o", " init process\r\r\n"] 141 | [18.833083, "o", "[ 0.596109] Using default interface naming scheme 'v252'.\r\r\n"] 142 | [18.940655, "o", "\u001b7\u001b[999;999H\u001b[6n\u001b8"] 143 | [19.063519, "o", "[ 0.826372] quiz: starting profile init: zfs\r\r\n"] 144 | [19.464147, "o", "[ 1.226909] spl: loading out-of-tree module taints kernel.\r\r\n"] 145 | [20.520866, "o", "[ 2.283866] zfs: module license 'CDDL' taints kernel.\r\r\n"] 146 | [20.52091, "o", "[ 2.283949] Disabling lock debugging due to k"] 147 | [20.520987, "o", "ernel taint\r\r\n"] 148 | [21.448654, "o", "[ 3.211551] ZFS: Loaded module v2.2.99-62_g28fdf9f64 (DEBUG mode), ZFS pool v"] 149 | [21.448683, "o", "ersion 5000, ZFS filesystem version 5\r\r\n"] 150 | [21.449328, "o", "[ 3.212315] quiz: starting pr"] 151 | [21.449376, "o", "ofile init: memdev\r\r\n"] 152 | [21.500683, "o", "[ 3.263530] quiz: memdev: created quizm0\r\r\n"] 153 | [21.556316, "o", "[ 3.319163] quiz: memdev: created quizm1\r\r\n"] 154 | [21.604273, "o", "[ 3.367160] quiz: memdev: created quizm2\r\r\n"] 155 | [21.773459, "o", "[ 3.536374] quiz: memdev: created quizm3\r\r\n"] 156 | [21.773721, "o", "[ 3.536663] quiz: starting user program\r\r\n"] 157 | [21.777563, "o", "[INFO tini (1)] Spawned child process '/bin/sh' with pid '545'\r\r\n"] 158 | [21.779252, "o", "+ "] 159 | [21.779337, "o", "zpool create"] 160 | [21.779374, "o", " tank quizm0 quizm1\r\r\n"] 161 | [22.160409, "o", "+ zpool status"] 162 | [22.160495, "o", "\r\r\n"] 163 | [22.168396, "o", " pool: tank\r\r\n state: ONLINE\r\r\nconfig:\r\r\n\r\r\n\tNAME STATE READ WRITE CKSUM"] 164 | [22.168517, "o", "\r\r\n\ttank ONLINE 0 0 0\r\r\n\t quizm0 ONLINE 0 0 0\r\r\n\t quizm1 ONLINE 0 0 0\r\r\n\r\r\n"] 165 | [22.168579, "o", "errors: No known data errors\r\r\n"] 166 | [22.169356, "o", "+ sleep"] 167 | [22.169443, "o", " 5\r\r\n"] 168 | [27.187316, "o", "[INFO tini (1)] Main child exited normally (with status '0')\r\r\n"] 169 | [27.187687, "o", "[ 8.950205] Kernel panic - not syncing: Attempted to kill ini"] 170 | [27.187874, "o", "t! exitcode=0x00000000\r\r\n[ 8.950615] CPU: 1 PID: 1 Comm: tini Tainted:"] 171 | [27.18814, "o", " P O 5.10.170 #3\r\r\n"] 172 | [27.188311, "o", "[ 8.950944] Call Trace:\r\r\n"] 173 | [27.188453, "o", "[ 8.951139] dump_stack+0x57/"] 174 | [27.188592, "o", "0x6e\r\r\n[ 8.951378] "] 175 | [27.18865, "o", "panic+0x10e/0x2cc\r\r\n"] 176 | [27.188831, "o", "[ 8.951584] "] 177 | [27.18899, "o", "do_exit.cold+0xa7/0xb3\r\r\n[ 8.951784] do_group_exit+0x"] 178 | [27.1892, "o", "33/0xa0\r\r\n"] 179 | [27.189347, "o", "[ 8.951981] __x64_sys_exit_group+0x14/0x20\r\r\n[ 8.952169] do_syscall_64+0x"] 180 | [27.189388, "o", "30/0x40\r\r\n"] 181 | [27.189587, "o", "[ 8.952340] entry_SYSCALL_64_after_hwframe+0x61/0xc6\r\r\n"] 182 | [27.189817, "o", "[ 8.952537] R"] 183 | [27.189977, "o", "IP: 0033:0x7f8366824249\r\r\n[ 8.952700] Code: 00 4c 8b 05 b9 db 0f 00 be "] 184 | [27.190125, "o", "e7 00 00 00 ba 3c 00 00 00 eb 12 0f 1f 44 00 00 89 d0 0f 05 48 3"] 185 | [27.190276, "o", "d 00 f0 ff ff 77 1c f4 89 f0 0f 05 <48> 3d 00 f0 ff ff 76 e7 f7 "] 186 | [27.190446, "o", "d8 64 41 89 00 eb df 0f 1f 80 00 00 00\r\r\n"] 187 | [27.190585, "o", "[ 8.953374] R"] 188 | [27.190771, "o", "SP: 002b:00007ffc6ae77328 EFLAGS"] 189 | [27.190825, "o", ": 00000246 ORIG_RAX: 00000000000000e7\r\r\n"] 190 | [27.191105, "o", "[ 8.953769] RAX: ffffffffffff"] 191 | [27.191276, "o", "ffda RBX: 00007f836691e9e0 RCX: 00007f8366824249\r\r\n[ 8.954103] R"] 192 | [27.191335, "o", "DX: 000000000000"] 193 | [27.191583, "o", "003c RSI: 00000000000000e7 RDI: 0000000000000000\r\r\n"] 194 | [27.191632, "o", "[ 8.954472] R"] 195 | [27.191816, "o", "BP: 0000000000000000 R08: ffffffffffffff80 R09: "] 196 | [27.192036, "o", "00007ffc6ae7724f\r\r\n"] 197 | [27.192103, "o", "[ 8.954820] R10: 00007ffc6ae771d0 R11: 000000"] 198 | [27.192343, "o", "0000000246 R12: "] 199 | [27.192487, "o", "00007f836691e9e0\r\r\n[ 8.955268] R13: 00007f836692"] 200 | [27.192587, "o", "42e0 R14: 0000000000000001 R15: 00007f83669242c8"] 201 | [27.19271, "o", "\r\r\n"] 202 | [27.303535, "o", "[quiz] 20230909-22:51:08 done\r\n"] 203 | [27.339346, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m⇡\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 204 | [29.691242, "o", "\u001b[?2004l\r\r\nexit\r\n"] 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🧩 quiz: a tool for rapid OpenZFS development 2 | 3 | **quiz** is a program to support fast edit-compile-test cycles for Linux kernel development, with a focus on OpenZFS. At its heart its a qemu-based microvm, stripped down to the essentials to setup and boot a VM and start a test program in seconds. 4 | 5 | > [!NOTE] 6 | > [I just presented quiz at EO2025](https://2025.everythingopen.au/schedule/presentation/77/), which generated some new interest, and reminded me just how out of date this README is. The "quick start" section below is definitely good, I wrote and tested it on 2025-01-22. Beyond that is right in spirit, but behind in some details. I'll get it rewritten as soon as I can. Thanks for your patience! 7 | > -- @robn, 2025-01-23. 8 | 9 | ## Quick start 10 | 11 | For Debian 12 (bookworm). 12 | 13 | Install prerequisites: 14 | 15 | ``` 16 | # for quiz 17 | $ sudo apt install git curl rsync qemu-system-x86 18 | 19 | # for kernel build 20 | $ sudo apt install make gcc flex bison libelf-dev bc libssl-dev 21 | 22 | # for root image build 23 | $ sudo apt install mmdebstrap genext2fs 24 | ``` 25 | 26 | Clone the repo: 27 | 28 | ``` 29 | $ git clone https://github.com/robn/quiz.git 30 | ``` 31 | 32 | Build a kernel: 33 | 34 | ``` 35 | $ ./quiz-kernel -k 6.17 36 | ``` 37 | 38 | Build the root image: 39 | 40 | ``` 41 | $ ./quiz-root 42 | ``` 43 | 44 | Start the VM: 45 | 46 | ``` 47 | $ ./quiz 48 | ``` 49 | 50 | ## Motivation 51 | 52 | My preferred programming style is highly interactive and exploratory, which requires a fast edit-compile-test cycle. But then I started working I work on [OpenZFS](https://openzfs.org), which is a big chunk of kernel code. Kernel code means developing on either real hardware or a VM, which tend to be awkward to get real code onto, and then, being kernel code, its pretty easy to crash, wedge or otherwise damage the kernel, requiring a reboot. 53 | 54 | I wanted a way to work on OpenZFS just like I’d work on any other program - make a change, compile it, run it and see what happens. I happened to know that microVMs were getting to the point where booting in a fraction of a second was possible, so I decided to see if I could use one for this. **quiz** is what I came up with. 55 | 56 | ## Note 57 | 58 | This is still pretty rough; you need to be willing to get your hands dirty and customise things, and its still firmly in the experimental stage: I change how things work pretty often, as I understand better what I need. 59 | 60 | That said, I'm using this to spin up tens and sometimes hundreds of VMs every day, doing Real Programming and furiously creating value for the shareholders. It does work and is safe to play with! 61 | 62 | Just don't treat anything here as more than "highly experimental". 63 | 64 | ## Demo 65 | 66 | Simple boot to prompt: 67 | 68 | [![quiz boot](demo/boot.gif)](https://asciinema.org/a/gQAwKSBnaDiZ6ZiO6ocaARd61) 69 | 70 | Creating a ZFS pool over memory-backed devices: 71 | 72 | [![quiz ZFS pool create](demo/zfs.gif)](https://asciinema.org/a/ZtZvX6MzK5y7HYsuEE7STaEbn) 73 | 74 | Running (part of) the ZFS test suite: 75 | 76 | [![quiz ZFS test suite run](demo/zfs-test.gif)](https://asciinema.org/a/kZ5TeTaqH7aU2xuJHSdDDu4at) 77 | 78 | The new interactive mode, which runs tmux inside the VM and makes it much easier to look around. 79 | 80 | [![interactive quiz with tmux](demo/quiz-tmux.gif)](https://asciinema.org/a/Ichfxm2Nojb8rXJzwjmJ9UPbj) 81 | 82 | ## Setup 83 | 84 | ### Install prerequisites 85 | 86 | On a Debian 12 (bookworm) system you’ll need at least: 87 | 88 | * `qemu-system-x86` 89 | * `mmdebstrap` 90 | * kernel build deps 91 | 92 | ### Build the kernel 93 | 94 | Run `quiz-kernel`. This will grab kernel source, compile it with a very minimal config to support only what’s needed for the microvm, and install it into the system dir. 95 | 96 | It will also set up the "work" dir, which is where kernel modules build artifacts and whatever else gets "installed" into the VM. 97 | 98 | ### Build the root image 99 | 100 | Run `quiz-root`. This will generate a barely-there Debian root image. 101 | 102 | ### Build OpenZFS 103 | 104 | The configure and install commands are quite involved to get it to properly target the work dir. The `quiz-zfs` wrapper is there to help with this. 105 | 106 | From an OpenZFS checkout: 107 | 108 | ``` 109 | $ ./autogen.sh 110 | $ ~/quiz/quiz-zfs configure --enable-debug --enable-debuginfo # your configure options here 111 | $ make -j6 112 | $ ~/quiz/quiz-zfs make install 113 | ``` 114 | 115 | ### Run it 116 | 117 | Simple boot to a shell: 118 | 119 | ``` 120 | $ ./quiz 121 | [quiz] 20230909-23:35:00 starting microvm 122 | [ 0.318686] brd: module loaded 123 | [ 0.445527] loop: module loaded 124 | [ 0.451687] virtio_blk virtio2: [vda] 1608310 512-byte logical blocks (823 MB/785 MiB) 125 | ... 126 | [ 0.520927] Run /sbin/init as init process 127 | [ 0.640503] Using default interface naming scheme 'v252'. 128 | [ 0.851721] quiz: starting user program 129 | [INFO tini (1)] Spawned child process '/bin/bash' with pid '511' 130 | bash: cannot set terminal process group (-1): Inappropriate ioctl for device 131 | bash: no job control in this shell 132 | root@quiz:/# 133 | ``` 134 | 135 | or run a program directly: 136 | 137 | ``` 138 | $ ./quiz uname -a 139 | [quiz] 20230909-23:35:37 creating run script 140 | [quiz] 20230909-23:35:37 starting microvm 141 | [ 0.317245] brd: module loaded 142 | [ 0.456128] loop: module loaded 143 | [ 0.463744] virtio_blk virtio2: [vda] 1608310 512-byte logical blocks (823 MB/785 MiB) 144 | ... 145 | [ 0.523497] Run /sbin/init as init process 146 | [ 0.714328] Using default interface naming scheme 'v252'. 147 | [ 0.913468] quiz: starting user program 148 | [INFO tini (1)] Spawned child process '/bin/sh' with pid '511' 149 | + uname -a 150 | Linux quiz 5.10.170 #3 SMP Wed Jun 21 15:52:50 AEST 2023 x86_64 GNU/Linux 151 | [INFO tini (1)] Main child exited normally (with status '0') 152 | ``` 153 | 154 | Include some profiles: 155 | 156 | ``` 157 | $ ./quiz -p zfs zpool status 158 | $ ./quiz -p zfs zpool status 159 | [quiz] 20230909-23:41:05 including profile: zfs 160 | [quiz] 20230909-23:41:05 creating run script 161 | [quiz] 20230909-23:41:05 starting microvm 162 | [ 0.318037] brd: module loaded 163 | [ 0.444730] loop: module loaded 164 | [ 0.452162] virtio_blk virtio2: [vda] 1608310 512-byte logical blocks (823 MB/785 MiB) 165 | ... 166 | [ 0.886639] quiz: starting profile init: zfs 167 | [ 1.075146] spl: loading out-of-tree module taints kernel. 168 | [ 2.223443] zfs: module license 'CDDL' taints kernel. 169 | [ 2.223489] Disabling lock debugging due to kernel taint 170 | [ 3.145029] ZFS: Loaded module v2.2.99-62_g28fdf9f64 (DEBUG mode), ZFS pool version 5000, ZFS filesystem version 5 171 | [ 3.146129] quiz: starting user program 172 | [INFO tini (1)] Spawned child process '/bin/sh' with pid '526' 173 | + zpool status 174 | no pools available 175 | [INFO tini (1)] Main child exited normally (with status '0') 176 | ``` 177 | 178 | ## Config 179 | 180 | Some amount of config can be done by creating a `quiz.cfg`. Defaults are set in `quiz-config` (which loads `quiz.cfg` to override them). The core scripts and profiles are configured this way. 181 | 182 | ## Profiles 183 | 184 | Profiles are quiz's extension mechanism. They introduce additional setup commands, config files or even whole programs into the VM as its being generated. The idea is that you can just enable the bits you need as you need them, to keep the boot time as small as possible for any given task. 185 | 186 | Profiles are enabled with the `-p` switch to `quiz`, or via the `QUIZ_PROFILE` config variable. 187 | 188 | The following profiles exist: 189 | 190 | * `blockdev`: creates some block devices, backed by files on the host and exposed to the VM through `virtio-blk`. They will appear as `/dev/quizbX`. 191 | * `memdev`: creates some block devices, backed by files on `tmpfs` inside the guest. They will appear as `/dev/quizm0`. 192 | * `zfs`: runs `depmod` to ensure the latest modules in the work dir have been, and then loads them into the VM kernel as part of the boot sequence. 193 | * `ztest`: adds a couple of hacks into the VM to allow the ZFS test suite to run properly. 194 | 195 | Profiles are in the `profile/` dir, each in their own named dir. There's three main hooks available: 196 | 197 | * If `setup` exists, it will be sourced by the `quiz` program before the VM is started (that is, it runs on the host) 198 | * If `init` exists, it will be sourced by the `init2` second-stage boot inside the VM, before control is handed to the shell or user program 199 | * Any other files will be copied into the work dir at the given paths, and so be available inside the VM after it boots 200 | 201 | Note that profiles currently have no way to influence the kernel config or the root filesystem, which is a problem if a profile needs something from it. I haven't decided what, if anything, to do about this yet. 202 | 203 | ## Todo 204 | 205 | * more profiles 206 | * persistent blockdevs 207 | * mdadm stuff (fake error environments) 208 | * pool create/import 209 | * a good way to get stuff back to the host (logs, test artifacts, etc) 210 | * multi-instance 211 | * this should really be something you use inside your OpenZFS worktree, so that they don't trample on each other 212 | * cleaner lines of integration with host 213 | * there's the place to install to, and then profile-generated stuff, and the internal .quiz/ work area, and then there's stuff the user wants to persist across runs, and further stuff that the user wants to bring into every VM (eg test programs). its not clear what should go where yet 214 | * just one program 215 | * it should just be `quiz foo`, and be on your path 216 | * more architectures 217 | * anything qemu supports should be possible. in particular, I would like a big-endian architecture 218 | * FreeBSD host support (ie bhyve instead of kvm) 219 | * qemu may not have support, so either make that happen (!) or find a different monitor package 220 | * FreeBSD guest support 221 | * wanted for OpenZFS dev on FreeBSD. [recent work on boot times in microvms](https://www.usenix.org/publications/loginonline/freebsd-firecracker) make this both plausible and attractive 222 | 223 | ## More info 224 | 225 | * Blog post: [quiz: a tool for rapid OpenZFS development](https://despairlabs.com/blog/posts/2024-03-04-quiz-rapid-openzfs-development/) 226 | * BSDCan 2024 presentation: [quiz: tiny VMs for kernel development](https://despairlabs.com/presentations/quiz/) 227 | -------------------------------------------------------------------------------- /demo/zfs-test.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 80, "height": 25, "timestamp": 1694263994, "env": {"SHELL": "/bin/bash", "TERM": "xterm-kitty"}, "title": "quiz ZFS test suite run"} 2 | [0.035859, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m⇡\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 3 | [0.982699, "o", "."] 4 | [1.157014, "o", "/"] 5 | [1.35636, "o", "q"] 6 | [1.466632, "o", "u"] 7 | [1.54668, "o", "i"] 8 | [1.686924, "o", "z"] 9 | [1.837288, "o", " "] 10 | [1.914974, "o", "-"] 11 | [2.115633, "o", "p"] 12 | [2.210266, "o", " "] 13 | [2.277709, "o", "z"] 14 | [2.485023, "o", "f"] 15 | [2.652927, "o", "s"] 16 | [2.760213, "o", ","] 17 | [2.901517, "o", "z"] 18 | [3.11385, "o", "t"] 19 | [3.263552, "o", "e"] 20 | [3.433858, "o", "s"] 21 | [3.586978, "o", "t"] 22 | [3.665205, "o", " "] 23 | [3.792983, "o", "/"] 24 | [3.999267, "o", "u"] 25 | [4.098188, "o", "s"] 26 | [4.178776, "o", "r"] 27 | [4.269527, "o", "/"] 28 | [4.488566, "o", "l"] 29 | [4.643721, "o", "o"] 30 | [4.703152, "o", "c"] 31 | [4.821233, "o", "a"] 32 | [4.943227, "o", "l"] 33 | [5.168884, "o", "/"] 34 | [5.313917, "o", "s"] 35 | [5.439756, "o", "h"] 36 | [5.541347, "o", "a"] 37 | [5.633123, "o", "r"] 38 | [5.75921, "o", "e"] 39 | [5.855361, "o", "/"] 40 | [6.024311, "o", "z"] 41 | [6.223355, "o", "f"] 42 | [6.419184, "o", "s"] 43 | [6.520502, "o", "/"] 44 | [6.681206, "o", "z"] 45 | [6.858313, "o", "f"] 46 | [7.085435, "o", "s"] 47 | [7.258618, "o", "-"] 48 | [7.396106, "o", "t"] 49 | [7.499651, "o", "e"] 50 | [7.68858, "o", "s"] 51 | [7.831137, "o", "t"] 52 | [7.971957, "o", "s"] 53 | [8.105962, "o", "."] 54 | [8.296631, "o", "s"] 55 | [8.469241, "o", "h"] 56 | [8.926238, "o", " "] 57 | [9.188187, "o", "-"] 58 | [9.400468, "o", "v"] 59 | [9.576484, "o", " "] 60 | [9.724591, "o", "-"] 61 | [9.958085, "o", "T"] 62 | [10.074218, "o", " "] 63 | [10.222434, "o", "b"] 64 | [10.277734, "o", "l"] 65 | [10.455341, "o", "o"] 66 | [10.563819, "o", "c"] 67 | [10.684904, "o", "k"] 68 | [10.857761, "o", "_"] 69 | [11.007953, "o", "c"] 70 | [11.102103, "o", "l"] 71 | [11.278741, "o", "o"] 72 | [11.492663, "o", "n"] 73 | [11.886484, "o", "i"] 74 | [12.01513, "o", "n"] 75 | [12.140463, "o", "g"] 76 | [12.242667, "o", " "] 77 | [12.384287, "o", "'"] 78 | [12.818268, "o", "&"] 79 | [12.984069, "o", "&"] 80 | [13.592786, "o", "' \r"] 81 | [13.759705, "o", " "] 82 | [13.897301, "o", "s"] 83 | [13.9857, "o", "l"] 84 | [14.129578, "o", "e"] 85 | [14.307043, "o", "e"] 86 | [14.394974, "o", "p"] 87 | [14.512465, "o", " "] 88 | [14.652086, "o", "5"] 89 | [14.882761, "o", "\r\n\u001b[?2004l\r"] 90 | [14.938408, "o", "[quiz] 20230909-22:53:29 including profile: zfs\r\n"] 91 | [14.951128, "o", "[quiz] 20230909-22:53:29 including profile: ztest\r\n"] 92 | [15.015445, "o", "[quiz] 20230909-22:53:29 creating run script\r\n"] 93 | [15.021975, "o", "[quiz] 20230909-22:53:29 starting microvm\r\n"] 94 | [15.909484, "o", "[ 0.318405] brd: module loaded\r\r\n"] 95 | [16.036648, "o", "[ 0.445157] loop: module loaded\r\r\n"] 96 | [16.04371, "o", "[ 0.452164] virtio_blk virtio2: [vda] 1608310 512-byte logica"] 97 | [16.044068, "o", "l blocks (823 MB/785 MiB)\r\r\n[ 0.452762] vda: detected capacity change from 0 to 823454720"] 98 | [16.044381, "o", "\r\r\n"] 99 | [16.06517, "o", "[ 0.473734] i8042: PNP: No PS/2 controller found.\r\r\n"] 100 | [16.067228, "o", "[ 0.475897] d"] 101 | [16.067559, "o", "evice-mapper: ioctl: 4.43.0-ioctl (2020-10-01) initialised: dm-devel@redhat.com\r\r\n"] 102 | [16.069911, "o", "[ 0.478602] NET: Registered p"] 103 | [16.069995, "o", "rotocol family 17\r\r\n"] 104 | [16.070255, "o", "[ 0.479054] 9pnet: Installing"] 105 | [16.070559, "o", " 9P2000 support\r\r\n"] 106 | [16.075402, "o", "[ 0.484061] NET: Registered p"] 107 | [16.075638, "o", "rotocol family 40\r\r\n"] 108 | [16.075701, "o", "[ 0.484459] o"] 109 | [16.075756, "o", "profile: using N"] 110 | [16.076051, "o", "MI interrupt.\r\r\n"] 111 | [16.076228, "o", "[ 0.484765] IPI shorthand broadcast: enabled\r\r\n"] 112 | [16.076301, "o", "[ 0.485032] AVX2 version of g"] 113 | [16.076494, "o", "cm_enc/dec engaged.\r\r\n[ 0.485335] AES CTR mode by8 "] 114 | [16.076628, "o", "optimization ena"] 115 | [16.076725, "o", "bled\r\r\n"] 116 | [16.086189, "o", "[ 0.494836] s"] 117 | [16.086523, "o", "ched_clock: Marking stable (4903"] 118 | [16.08659, "o", "03909, 4475182)->(508846202, -14067111)\r\r\n"] 119 | [16.087019, "o", "[ 0.495806] r"] 120 | [16.087233, "o", "egistered taskst"] 121 | [16.087433, "o", "ats version 1\r\r\n[ 0.496072] Loading compiled-in X.509 certificates\r\r\n"] 122 | [16.089773, "o", "[ 0.498550] EXT4-fs (vda): mounting ext2 file"] 123 | [16.09, "o", " system using the ext4 subsystem\r\r\n"] 124 | [16.0924, "o", "[ 0.501121] EXT4-fs (vda): mounted filesystem"] 125 | [16.092675, "o", " without journal. Opts: (null)\r\r\n[ 0.501442] VFS: Mounted root (ext2 filesyste"] 126 | [16.092917, "o", "m) readonly on d"] 127 | [16.093151, "o", "evice 254:0.\r\r\n"] 128 | [16.095689, "o", "[ 0.504481] F"] 129 | [16.095729, "o", "reeing unused ke"] 130 | [16.096122, "o", "rnel image (initmem) memory: 2332K\r\r\n"] 131 | [16.112395, "o", "[ 0.521054] Write protecting the kernel read-"] 132 | [16.112717, "o", "only data: 18432k\r\r\n"] 133 | [16.116466, "o", "[ 0.525172] Freeing unused kernel image (text"] 134 | [16.116708, "o", "/rodata gap) memory: 2040K\r\r\n"] 135 | [16.117196, "o", "[ 0.525919] Freeing unused ke"] 136 | [16.11752, "o", "rnel image (rodata/data gap) mem"] 137 | [16.117809, "o", "ory: 592K\r\r\n"] 138 | [16.119347, "o", "[ 0.528092] x"] 139 | [16.119612, "o", "86/mm: Checked W+X mappings: pas"] 140 | [16.119795, "o", "sed, no W+X pages found.\r\r\n[ 0.528502] Run /sbin/init as init process\r\r\n"] 141 | [16.447222, "o", "[ 0.856151] Using default interface naming sc"] 142 | [16.44732, "o", "heme 'v252'.\r\r\n"] 143 | [16.579984, "o", "\u001b7\u001b[999;999H\u001b[6n\u001b8"] 144 | [16.70886, "o", "[ 1.117458] quiz: starting pr"] 145 | [16.709029, "o", "ofile init: zfs\r\r\n"] 146 | [16.822433, "o", "[ 1.231339] spl: loading out-of-tree module taints kernel.\r\r\n"] 147 | [17.88471, "o", "[ 2.293544] zfs: module license 'CDDL' taints kernel.\r\r\n[ 2.293590] Disabling lock debugging due to kernel taint\r\r\n"] 148 | [18.808496, "o", "[ 3.217275] ZFS: Loaded module v2.2.99-62_g28fdf9f64 (DEBUG mode), ZFS pool version 5000, ZFS"] 149 | [18.808601, "o", " filesystem version 5\r\r\n"] 150 | [18.809762, "o", "[ 3.218605] quiz: starting user program\r\r\n"] 151 | [18.812914, "o", "[INFO tini (1)] Spawned child process '/bin/sh' with pid '526'\r\r\n"] 152 | [18.814295, "o", "+ "] 153 | [18.814356, "o", "/usr/local/share/zfs/zfs-tests.sh"] 154 | [18.814401, "o", " -v -T block_cloning\r\r\n"] 155 | [19.285035, "o", "\r\r\n"] 156 | [19.285184, "o", "--- Configuration ---\r\r\nRunfiles: /usr/local/share/zfs/runfiles/common.run,/usr/local/share/zfs/runfiles/linux.run"] 157 | [19.285237, "o", "\r\r\nSTF_TOOLS: /usr/local/share/zfs/test-runner\r\r\n"] 158 | [19.285326, "o", "STF_SUITE: /usr/local/share/zfs/zfs-tests\r\r\nSTF_PATH: /var/tmp/constrained_path.nBFqRU"] 159 | [19.285422, "o", "\r\r\n"] 160 | [19.285521, "o", "FILEDIR: /var/tmp\r\r\n"] 161 | [19.285563, "o", "FILES: /var/tmp/file-vdev0 /var/tmp/file-vdev1 /var/tmp/file-vdev2\r\r\n"] 162 | [19.285602, "o", "LOOPBACKS: /dev/loop0 /dev/loop1 /dev/loop2"] 163 | [19.285619, "o", "\r\r\n"] 164 | [19.285672, "o", "DISKS: loop0 loop1 loop2\r\r\n"] 165 | [19.285707, "o", "NUM_DISKS: 3\r\r\n"] 166 | [19.285748, "o", "FILESIZE: 4G"] 167 | [19.285781, "o", "\r\r\n"] 168 | [19.285821, "o", "ITERATIONS: 1\r\r\n"] 169 | [19.285862, "o", "TAGS: block_cloning\r\r\n"] 170 | [19.285911, "o", "STACK_TRACER: no\r\r\n"] 171 | [19.285953, "o", "Keep pool(s): rpool"] 172 | [19.285988, "o", "\r\r\n"] 173 | [19.286022, "o", "Missing util(s): \r\r\n"] 174 | [19.286056, "o", "\r\r\n"] 175 | [19.289331, "o", "/usr/local/share/zfs/test-runner/bin/test-runner.py -c \"/usr/local/share/zfs/runfiles/common.run,/usr/local/share/zfs/runfiles/linux.run\" -T \"block_cloning\" -i \"/usr/local/share/zfs/zfs-tests\" -I \"1\"\r\r\n"] 176 | [20.270307, "o", "Warning: Test 'pam_change_unmounted' removed from TestGroup '/usr/local/share/zfs/zfs-tests/tests/functional/pam' because it failed verification.\r\r\n"] 177 | [20.270715, "o", "Warning: Test 'pam_recursive' removed from TestGroup '/usr/local/share/zfs/zfs-tests/tests/functional/pam' because it failed verification.\r\r\n"] 178 | [20.352056, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/setup (run as root) [00:00] [PASS]\r\r\n"] 179 | [21.111571, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange (run as root) [00:00] [PASS]\r\r\n"] 180 | [21.937409, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial (run as root) [00:00] [PASS]\r\r\n"] 181 | [22.93118, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback (run as root) [00:00] [PASS]\r\r\n"] 182 | [23.715461, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone (run as root) [00:00] [PASS]\r\r\n"] 183 | [24.532772, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange (run as root) [00:00] [PASS]\r\r\n"] 184 | [25.382831, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial (run as root) [00:00] [PASS]\r\r\n"] 185 | [26.128767, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange (run as root) [00:00] [PASS]\r\r\n"] 186 | [26.712038, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlone (run as root) [00:00] [PASS]\r\r\n"] 187 | [27.342416, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_ficlonerange (run as root) [00:00] [PASS]\r\r\n"] 188 | [28.104995, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset (run as root) [00:00] [PASS]\r\r\n"] 189 | [28.839081, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg (run as root) [00:00] [PASS]\r\r\n"] 190 | [28.936112, "o", "Test (Linux): /usr/local/share/zfs/zfs-tests/tests/functional/block_cloning/cleanup (run as root) [00:00] [PASS]\r\r\n"] 191 | [28.936578, "o", "\r\r\nResults Summary"] 192 | [28.936646, "o", "\r\r\nPASS\t 13\r\r\n"] 193 | [28.936687, "o", "\r\r\nRunning Time:"] 194 | [28.93672, "o", "\t00:00:09\r\r\nPercent passed:"] 195 | [28.936736, "o", "\t100.0%"] 196 | [28.936797, "o", "\r\r\n"] 197 | [28.936815, "o", "Log directory:\t/var/tmp/test_results/20230909T125333\r\r\n"] 198 | [29.11039, "o", "\r\r\nTests with results other than PASS that are expected:\r\r\n\r\r\nTests with result of PASS that are unexpected:\r\r\n\r\r\nTests with results other than PASS that are unexpected:\r\r\n"] 199 | [29.237901, "o", "+ "] 200 | [29.238136, "o", "sleep 5\r\r\n"] 201 | [34.242784, "o", "[INFO tini (1)] Main child exited normally (with status '0')\r\r\n"] 202 | [34.24315, "o", "[ 18.651375] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000\r\r\n"] 203 | [34.243244, "o", "[ 18.651784] CPU: 1 PID: 1 Com"] 204 | [34.243542, "o", "m: tini Tainted: P O 5.10.170 #3\r\r\n"] 205 | [34.243715, "o", "[ 18.652202] C"] 206 | [34.243761, "o", "all Trace:\r\r\n[ 18.652373] "] 207 | [34.244021, "o", "dump_stack+0x57/0x6e\r\r\n"] 208 | [34.244151, "o", "[ 18.652571] panic+0x10e/0x2cc\r\r\n[ 18.652768] "] 209 | [34.244202, "o", "do_exit.cold+0xa"] 210 | [34.244356, "o", "7/0xb3\r\r\n[ 18.652960] "] 211 | [34.244403, "o", "do_group_exit+0x"] 212 | [34.244556, "o", "33/0xa0\r\r\n"] 213 | [34.244702, "o", "[ 18.653157] __x64_sys_exit_g"] 214 | [34.244835, "o", "roup+0x14/0x20\r\r\n[ 18.653337] do_syscall_64+0x"] 215 | [34.245027, "o", "30/0x40\r\r\n"] 216 | [34.2452, "o", "[ 18.653562] entry_SYSCALL_64_after_hwframe+0x61/0xc6\r\r\n[ 18.653816] R"] 217 | [34.245351, "o", "IP: 0033:0x7fb526dfc249\r\r\n[ 18.653961] C"] 218 | [34.245472, "o", "ode: 00 4c 8b 05"] 219 | [34.245591, "o", " b9 db 0f 00 be e7 00 00 00 ba 3"] 220 | [34.245643, "o", "c 00 00 00 eb 12 0f 1f 44 00 00 "] 221 | [34.24585, "o", "89 d0 0f 05 48 3d 00 f0 ff ff 77 1c f4 89 f0 0f 05 <48> 3d 00 f0 ff ff 76 e7 f7 "] 222 | [34.246007, "o", "d8 64 41 89 00 eb df 0f 1f 80 00 00 00\r\r\n"] 223 | [34.246254, "o", "[ 18.654702] RSP: 002b:00007ffd5d98bb88 EFLAGS"] 224 | [34.246499, "o", ": 00000246 ORIG_RAX: 00000000000000e7\r\r\n[ 18.655122] R"] 225 | [34.246548, "o", "AX: ffffffffffff"] 226 | [34.246579, "o", "ffda RBX: 00007f"] 227 | [34.246869, "o", "b526ef69e0 RCX: 00007fb526dfc249\r\r\n[ 18.655444] R"] 228 | [34.246966, "o", "DX: 000000000000"] 229 | [34.24701, "o", "003c RSI: 00000000000000e7 RDI: "] 230 | [34.247278, "o", "0000000000000000\r\r\n[ 18.655809] RBP: 0000000000000000 R08: ffffff"] 231 | [34.247485, "o", "ffffffff80 R09: 00007ffd5d98baaf"] 232 | [34.247657, "o", "\r\r\n[ 18.656089] R10: 00007ffd5d98ba30 R11: 0000000000000246 R12: "] 233 | [34.247833, "o", "00007fb526ef69e0\r\r\n[ 18.656426] R13: 00007fb526ef"] 234 | [34.247997, "o", "c2e0 R14: 000000"] 235 | [34.248184, "o", "0000000001 R15: 00007fb526efc2c8\r\r\n"] 236 | [34.328015, "o", "[quiz] 20230909-22:53:48 done\r\n"] 237 | [34.361704, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m⇡\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 238 | [35.991446, "o", "\u001b[?2004l\r\r\nexit\r\n"] 239 | -------------------------------------------------------------------------------- /quiz-kernel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # 8 | # Copyright (c) 2023-2025, Rob Norris 9 | 10 | set -uo pipefail 11 | 12 | usage() { 13 | cat < kernel to build 19 | (can be used multiple times) 20 | -a architecture to build for 21 | -e/-d/-m set kernel config key to enable/disable/module (Y/N/M) 22 | (can be used multiple times) 23 | -u update standard config for this kernel minor version 24 | -L build with LLVM/Clang 25 | -T initialise missing config from tinyconfig 26 | -C don't install kernel config before build 27 | -B don't build kernel 28 | -K rebuild all installed kernels 29 | (equivalent to -k -k ...) 30 | -U upgrade kernels (build latest for minor series) 31 | -X remove old kernels in same minor series 32 | -h this help 33 | EOF 34 | exit 1 35 | } 36 | 37 | trace() { 38 | local STAMP=$(date +%Y%m%d-%H:%M:%S) 39 | echo "[quiz-kernel] $STAMP $@" >&2 40 | } 41 | 42 | fail() { 43 | local TEXT=${@:-} 44 | if [[ -z $TEXT ]] ; then 45 | TEXT="[${BASH_SOURCE[0]}:${BASH_LINENO[0]}: $BASH_COMMAND]" 46 | fi 47 | trace "FATAL $TEXT" 48 | exit 1 49 | } 50 | trap fail ERR 51 | 52 | RUNDIR=$(realpath $(dirname $0)) 53 | source $RUNDIR/quiz-config 54 | source $RUNDIR/quiz-lib 55 | 56 | opt_arch="" 57 | opt_kernel="" 58 | opt_init_config="" 59 | opt_no_config="" 60 | opt_no_build="" 61 | opt_llvm="" 62 | opt_update_config="" 63 | opt_modify_config="" 64 | opt_all_kernels="" 65 | opt_upgrade="" 66 | opt_upgrade_cleanup="" 67 | 68 | OPTIND=1 69 | while getopts "a:k:ICBe:d:m:uLKUXh" opt 70 | do 71 | case "$opt" in 72 | 'a') opt_arch=$OPTARG ;; 73 | 'k') opt_kernel="$opt_kernel $OPTARG" ;; 74 | 'I') opt_init_config=1 ;; 75 | 'C') opt_no_config=1 ;; 76 | 'B') opt_no_build=1 ;; 77 | 'e') opt_modify_config="$opt_modify_config -e $OPTARG" ;; 78 | 'd') opt_modify_config="$opt_modify_config -d $OPTARG" ;; 79 | 'm') opt_modify_config="$opt_modify_config -m $OPTARG" ;; 80 | 'u') opt_update_config=1 ;; 81 | 'L') opt_llvm=1 ;; 82 | 'K') opt_all_kernels=1 ;; 83 | 'U') opt_upgrade=1 ;; 84 | 'X') opt_upgrade_cleanup=1 ;; 85 | 'h') usage ;; 86 | *) exit 1 ;; 87 | esac 88 | done 89 | shift $(expr $OPTIND - 1) 90 | 91 | quiz_arch_vars ${opt_arch:-$QUIZ_ARCH} 92 | 93 | cd $RUNDIR 94 | 95 | if [[ -n $opt_kernel && -n $opt_all_kernels ]] ; then 96 | fail "invalid kernel version options; can't use -k and -K together" 97 | fi 98 | if [[ -z $opt_kernel && -z $opt_all_kernels ]] ; then 99 | fail "no kernel version supplied; one of -k or -K required" 100 | fi 101 | 102 | if [[ -n $opt_all_kernels ]] ; then 103 | opt_kernel=$(ls system/kernel/$_quiz_arch_kernel/kernel-* | cut -d- -f2 | sort -V) 104 | if [[ -z $opt_kernel ]] ; then 105 | fail "no kernels found in system/kernel/$_quiz_arch_kernel" 106 | fi 107 | fi 108 | 109 | # dedicate half the cpus, rounded up, to building kernels 110 | ncpus=$((($(nproc)+1)/2)) 111 | trace "using $ncpus cpus for kernel builds" 112 | 113 | # makeopts are switches for make. makevars are variables added to the end 114 | makeopts="-j$ncpus" 115 | makevars="" 116 | 117 | if [[ -n $opt_llvm ]] ; then 118 | IFS=: 119 | best_clang=$(find $PATH -maxdepth 1 -executable -name "clang-??" -print | \ 120 | sed -Ee 's/^.+-//' | sort -r | head -1) 121 | unset IFS 122 | if [[ -z "$best_clang" ]] ; then 123 | trace "no specific clang found, setting LLVM=1" 124 | best_clang=1 125 | else 126 | trace "found clang-$best_clang, setting LLVM=-$best_clang" 127 | best_clang="-$best_clang" 128 | fi 129 | makevars="$makevars LLVM=$best_clang" 130 | fi 131 | 132 | if [[ -z $_quiz_arch_native ]] ; then 133 | trace "setting up for cross-compile: $_quiz_arch_kernel" 134 | makevars="$makevars CROSS_COMPILE=${_quiz_arch_prefix}- ARCH=$_quiz_arch_kernel" 135 | fi 136 | 137 | mkdir -p build/kernel 138 | 139 | declare -A kernel_sumfile 140 | 141 | kernel_versions="" 142 | for kver in $opt_kernel ; do 143 | _quiz_kernel_vars $kver 144 | if [[ $_quiz_kmajor && $_quiz_kminor && ( -z $_quiz_kpatch || -n $opt_upgrade ) ]] ; then 145 | if [[ -z ${kernel_sumfile[$_quiz_kmajor]:-} ]] ; then 146 | sumfile=build/kernel/sha256sums.$_quiz_kmajor 147 | trace "fetching list of available kernels for v$_quiz_kmajor.x" 148 | if [[ ! -e $sumfile ]] ; then 149 | touch --date=@0 $sumfile 150 | fi 151 | curl -# -f -o $sumfile -z $sumfile -R \ 152 | https://cdn.kernel.org/pub/linux/kernel/v$_quiz_kmajor.x/sha256sums.asc 153 | kernel_sumfile[$_quiz_kmajor]=$sumfile 154 | fi 155 | latest=$(cat ${kernel_sumfile[$_quiz_kmajor]} | \ 156 | sed -Ene "/linux-.+\.tar\.xz/ { s/.*linux-($_quiz_kmajor\.$_quiz_kminor(\.[0-9]+)?)\.tar\.xz/\1/ p }" | tail -1) 157 | if [[ -z $latest ]] ; then 158 | trace "no latest kernel matching $_quiz_kmajor.$_quiz_kminor" 159 | kver="" 160 | elif [[ -n $opt_upgrade ]] ; then 161 | _quiz_kernel_vars $latest 162 | if [[ -z $_quiz_kpatch ]] ; then 163 | latest="$_quiz_kmajor.$_quiz_kminor.0" 164 | fi 165 | if [[ $latest == $kver ]] ; then 166 | trace "$kver already latest, not rebuilding" 167 | kver="" 168 | else 169 | trace "will upgrade $kver to $latest" 170 | kver=$latest 171 | fi 172 | else 173 | trace "will build $latest for $kver" 174 | kver=$latest 175 | fi 176 | fi 177 | if [[ $kver ]] ; then 178 | kernel_versions="$kernel_versions $kver" 179 | fi 180 | done 181 | 182 | kernel_versions=$(echo $kernel_versions | xargs -n1 | sort -V | uniq | xargs) 183 | trace "will build kernel versions: $kernel_versions" 184 | 185 | kdest=$RUNDIR/system/kernel/$_quiz_arch_kernel 186 | 187 | build_kernel() { 188 | local kver=$1 189 | 190 | quiz_kernel_vars $kver 191 | 192 | case $_quiz_ktype in 193 | release) 194 | ksrctype=tar 195 | ktar=linux-$_quiz_ksrcver.tar.xz 196 | kurl=https://cdn.kernel.org/pub/linux/kernel/v$_quiz_kmajor.x/$ktar 197 | kzopt=J 198 | kuntar=linux-$_quiz_ksrcver 199 | ;; 200 | rc) 201 | ksrctype=tar 202 | ktar=linux-$_quiz_ksrcver.tar.gz 203 | kurl=https://git.kernel.org/torvalds/t/$ktar 204 | kzopt=z 205 | kuntar=linux-$_quiz_ksrcver 206 | ;; 207 | next) 208 | ksrctype=tar 209 | ktar=next-$_quiz_ktype_patch.tar.gz 210 | kurl=https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/snapshot/linux-next-$ktar 211 | kzopt=z 212 | kuntar=linux-next-next-$_quiz_ktype_patch 213 | ;; 214 | *) 215 | fail "unknown kernel version type: $_quiz_ktype" 216 | esac 217 | 218 | trace "preparing build: $_quiz_kver ($_quiz_ktype)" 219 | 220 | ksrc=$RUNDIR/build/kernel/$kuntar 221 | 222 | if [[ -d $ksrc ]] ; then 223 | trace "using existing source dir: $ksrc" 224 | if [[ $ksrctype == 'git' ]] ; then 225 | trace "cleaning up git dir: $ksrc" 226 | git -C $ksrc clean -fdx 227 | fi 228 | else 229 | trace "setting up for build in: $ksrc" 230 | pushd build/kernel > /dev/null 231 | case $ksrctype in 232 | tar) 233 | if [[ -f $ktar ]] ; then 234 | trace "using existing tarball: $ktar" 235 | else 236 | trace "downloading: $kurl" 237 | mkdir -p tmp 238 | curl \ 239 | --progress-bar \ 240 | --output-dir tmp \ 241 | --output $ktar \ 242 | --continue-at - \ 243 | --location \ 244 | --fail \ 245 | $kurl 246 | mv tmp/$ktar $ktar 247 | fi 248 | tar xf$kzopt $ktar 249 | ;; 250 | git) 251 | trace "cloning: $kgittag @ $kgiturl" 252 | git clone \ 253 | --config advice.detachedHead=false \ 254 | --depth 1 \ 255 | --branch $kgittag \ 256 | $kgiturl linux-$_quiz_ksrcver 257 | ;; 258 | *) 259 | fail "unknown kernel source type: $ksrctype" 260 | ;; 261 | esac 262 | popd > /dev/null 263 | fi 264 | 265 | if [[ -f $ksrc/.config ]] ; then 266 | if ! grep -q -m1 "^# Linux/$_quiz_arch_kernel" $ksrc/.config ; then 267 | trace "existing source dir was for a different architecture, cleaning it" 268 | make $makeopts -s -C $ksrc distclean $makevars 269 | fi 270 | fi 271 | 272 | _do_mrproper=0 273 | if [[ $_quiz_ktype = "next" ]] ; then 274 | # get rid of -rcX or similar. this is already too complicated 275 | sed -i -E 's/^(EXTRAVERSION =) .*/\1/' $ksrc/Makefile 276 | 277 | if [[ ! -f $ksrc/include/config/auto.conf ]] ; then 278 | # sigh, circular dependency. we need a config set up to be able to 279 | # query the version. which we need for a config 280 | trace "prepping source tree for pre-config" 281 | make $makeopts -s -C $ksrc tinyconfig prepare $makevars 282 | _do_mrproper=1 283 | fi 284 | 285 | quiz_kernel_vars $(make -s -C $ksrc kernelrelease) 286 | trace "updated version from makefile: $_quiz_kver" 287 | 288 | if [[ $_do_mrproper ]] ; then 289 | # and then cleanup from above, so it'll start fresh with the new config 290 | make $makeopts -s -C $ksrc mrproper $makevars 291 | fi 292 | fi 293 | 294 | kcfg=config-$_quiz_kmajor.$_quiz_kminor 295 | if [[ -z $opt_no_config ]] ; then 296 | found_kcfg="" 297 | if [[ -f kernel/$_quiz_arch_kernel/$kcfg ]] ; then 298 | found_kcfg=$kcfg 299 | else 300 | found_kcfg=$(find kernel/$_quiz_arch_kernel/ -name "config-$_quiz_kmajor.*" | \ 301 | cut -f3 -d/ | sort -V | tail -1) 302 | if [[ -z $found_kcfg ]] ; then 303 | found_kcfg=$(find kernel/$_quiz_arch_kernel/ -name "config-*" | \ 304 | cut -f3 -d/ | sort -V | tail -1) 305 | fi 306 | fi 307 | if [[ -z $found_kcfg ]] ; then 308 | if [[ -z $opt_init_config ]] ; then 309 | fail "no usable config found!" 310 | fi 311 | trace "no usable config found, bootstrapping from tinyconfig" 312 | make $makeopts -s -C $ksrc tinyconfig $makevars 313 | # XXX encode other essential config here -- robn, 2025-11-12 314 | else 315 | if [[ $kcfg != $found_kcfg ]] ; then 316 | trace "specific config not found, using fallback: $found_kcfg" 317 | fi 318 | 319 | trace "installing config: $found_kcfg" 320 | cp kernel/$_quiz_arch_kernel/$found_kcfg $ksrc/.config 321 | fi 322 | else 323 | trace "NOT installing config as requested" 324 | fi 325 | 326 | pushd $ksrc > /dev/null 327 | 328 | if [[ -n $opt_modify_config ]] ; then 329 | trace "updating config from commandline switches" 330 | scripts/config $opt_modify_config 331 | fi 332 | 333 | trace "compiling config: $_quiz_ksrcver" 334 | make $makeopts -s olddefconfig prepare $makevars 335 | 336 | if [[ -z $opt_no_build ]] ; then 337 | 338 | # XXX image_name actually returns the name of the image produced by the 339 | # last completed build. this has bitten me when bootstrapping a new 340 | # architecture, when I realise that I'm taking a compressed image 341 | # but the bootloader wants a raw image. the next run after I realise 342 | # fixes it, because the _previous_ run did an uncompressed image. 343 | # 344 | # it's not clear to me what, if any, solution is needed here. doing 345 | # a mrproper round like above definitely fixes it, but we lose all 346 | # the output from the previous run. maybe I should burn all images 347 | # from the previous run too? or maybe doesn't matter, and this is just 348 | # a "note to self" that I'll find when I'm ripping my hair out next 349 | # time. 350 | # 351 | # -- robn, 2025-11-12 352 | 353 | kimagepath=$(make -s $makeopts image_name $makevars) 354 | kimage=$(basename $kimagepath) 355 | 356 | trace "building kernel: $_quiz_ksrcver ($kimage)" 357 | make $makeopts $kimage modules $makevars 358 | 359 | trace "installing completed kernel: $_quiz_kver" 360 | 361 | mkdir -p $kdest 362 | 363 | # merged /usr setup 364 | mkdir -p $kdest/usr/lib 365 | ln -sf usr/lib $kdest/lib 366 | 367 | # install everything we need. the kernel's own install stuff doesn't quite 368 | # do everything the way we want, so we do a few things ourselves 369 | 370 | # XXX delete the old stuff first? -- robn, 2025-01-13 371 | 372 | # kernel and system map 373 | cp -vf $ksrc/$kimagepath $kdest/kernel-$_quiz_kver 374 | cp -vf $ksrc/System.map $kdest/System.map-$_quiz_kver 375 | 376 | # modules tree 377 | make $makeopts -C $ksrc modules_install INSTALL_MOD_PATH=$kdest $makevars 378 | /sbin/depmod -b $kdest $_quiz_kver 379 | 380 | # extern module build, so we're not dependent on kernel source to rebuild 381 | # this is roughly what you find symlinked from /lib/modules/XXX/build 382 | # on stock Linux systems. other architectures may require more/different 383 | # things, refer to builddeb/buildrpm/install-extmod-build in the kernel 384 | # source tree for details 385 | mkdir -p $kdest/kbuild/$_quiz_kver 386 | ( 387 | cd $ksrc 388 | archdir=arch/$_quiz_arch_kernel 389 | find Makefile vmlinux include -type f -o -type l 390 | find scripts tools -executable -type f -o -type l 391 | find $archdir -maxdepth 1 -name 'Makefile*' 392 | find $archdir -name include -o -name scripts -type d 393 | find $archdir/include Module.symvers include scripts -type f 394 | ) | tar -cf - -C $ksrc -T - | tar -xf - -C $kdest/kbuild/$_quiz_kver 395 | 396 | else 397 | trace "NOT building kernel as requested" 398 | fi 399 | 400 | popd > /dev/null 401 | 402 | if [[ -n $opt_update_config ]] ; then 403 | trace "updating standard config: $kcfg" 404 | cp $ksrc/.config kernel/$_quiz_arch_kernel/$kcfg 405 | fi 406 | 407 | trace "build finished: $_quiz_kver" 408 | 409 | if [[ -n $opt_upgrade_cleanup ]] ; then 410 | trace "removing old kernels in minor series: $_quiz_kmajor.$_quiz_kminor" 411 | find $kdest \ 412 | -name "*$_quiz_kmajor.$_quiz_kminor.*" -a \ 413 | ! -name "*$_quiz_kver" \ 414 | | xargs -r rm -r 415 | fi 416 | } 417 | 418 | kver_failed=() 419 | 420 | for kver in $kernel_versions ; do 421 | # capture errors in the build_kernel function by calling it in a subshell 422 | # we have to disable our error trap first, then reenable them inside the 423 | # subshell so that the function still early aborts, but the subshell doesn't 424 | # trigger our error trap. 425 | trap - ERR 426 | ( trap fail ERR ; build_kernel $kver ) 427 | rc=$? 428 | trap fail ERR 429 | 430 | if [[ $rc -ne 0 ]] ; then 431 | kver_failed+=($kver) 432 | fi 433 | done 434 | 435 | if [[ ${#kver_failed[*]} -ne 0 ]] ; then 436 | trace "kernels failed: ${kver_failed[*]}" 437 | fi 438 | 439 | # vim: ft=bash 440 | -------------------------------------------------------------------------------- /demo/boot.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 80, "height": 25, "timestamp": 1694263664, "env": {"SHELL": "/bin/bash", "TERM": "xterm-kitty"}, "title": "quiz boot"} 2 | [0.036139, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m⇡\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 3 | [1.568664, "o", "."] 4 | [1.783356, "o", "/"] 5 | [2.026172, "o", "q"] 6 | [2.162269, "o", "u"] 7 | [2.37411, "o", "i"] 8 | [2.664005, "o", "z"] 9 | [2.924076, "o", "\r\n\u001b[?2004l\r"] 10 | [2.950138, "o", "[quiz] 20230909-22:47:47 starting microvm\r\n"] 11 | [3.816709, "o", "[ 0.319468] brd: module loaded\r\r\n"] 12 | [3.947863, "o", "[ 0.450292] loop: module loaded\r\r\n"] 13 | [3.955235, "o", "[ 0.457743] virtio_blk virtio"] 14 | [3.95557, "o", "2: [vda] 1608310 512-byte logical blocks (823 MB/785 MiB)\r\r\n"] 15 | [3.95565, "o", "[ 0.458266] v"] 16 | [3.955912, "o", "da: detected capacity change fro"] 17 | [3.956133, "o", "m 0 to 823454720\r\r\n"] 18 | [3.976272, "o", "[ 0.478685] i8042: PNP: No PS/2 controller fo"] 19 | [3.976585, "o", "und.\r\r\n"] 20 | [3.977323, "o", "[ 0.479845] device-mapper: ioctl: 4.43.0-ioct"] 21 | [3.97742, "o", "l (2020-10-01) initialised: dm-devel@redhat.com\r"] 22 | [3.977638, "o", "\r\n"] 23 | [3.979549, "o", "[ 0.482176] NET: Registered p"] 24 | [3.979783, "o", "rotocol family 17\r\r\n"] 25 | [3.979986, "o", "[ 0.482667] 9"] 26 | [3.980108, "o", "pnet: Installing 9P2000 support\r\r\n"] 27 | [3.985551, "o", "[ 0.488102] NET: Registered p"] 28 | [3.98574, "o", "rotocol family 40\r\r\n"] 29 | [3.985878, "o", "[ 0.488612] o"] 30 | [3.986003, "o", "profile: using NMI interrupt.\r\r\n"] 31 | [3.986167, "o", "[ 0.488908] I"] 32 | [3.986283, "o", "PI shorthand broadcast: enabled\r\r\n"] 33 | [3.986505, "o", "[ 0.489221] A"] 34 | [3.986647, "o", "VX2 version of gcm_enc/dec engaged.\r\r\n"] 35 | [3.986822, "o", "[ 0.489558] A"] 36 | [3.986875, "o", "ES CTR mode by8 "] 37 | [3.987032, "o", "optimization enabled\r\r\n"] 38 | [3.997324, "o", "[ 0.499940] sched_clock: Mark"] 39 | [3.997394, "o", "ing stable (495297807, 4600251)-"] 40 | [3.997669, "o", ">(513750270, -13852212)\r\r\n"] 41 | [3.99832, "o", "[ 0.500908] registered taskst"] 42 | [3.998551, "o", "ats version 1\r\r\n[ 0.501198] Loading compiled-in X.509 certifi"] 43 | [3.99863, "o", "cates\r\r\n"] 44 | [4.000686, "o", "[ 0.503373] EXT4-fs (vda): mo"] 45 | [4.00074, "o", "unting ext2 file"] 46 | [4.000924, "o", " system using the ext4 subsystem\r\r\n"] 47 | [4.002311, "o", "[ 0.505035] E"] 48 | [4.002471, "o", "XT4-fs (vda): mo"] 49 | [4.00259, "o", "unted filesystem without journal. Opts: (null)\r\r\n[ 0.505291] VFS: Mounted root (ext2 filesyste"] 50 | [4.002697, "o", "m) readonly on device 254:0.\r\r\n"] 51 | [4.004642, "o", "[ 0.507378] F"] 52 | [4.004746, "o", "reeing unused kernel image (initmem) memory: 2332K\r\r\n"] 53 | [4.019424, "o", "[ 0.522137] Write protecting the kernel read-"] 54 | [4.019521, "o", "only data: 18432k\r\r\n"] 55 | [4.020736, "o", "[ 0.523454] Freeing unused kernel image (text/rodata gap) mem"] 56 | [4.020845, "o", "ory: 2040K\r\r\n"] 57 | [4.021037, "o", "[ 0.523713] Freeing unused kernel image (roda"] 58 | [4.021129, "o", "ta/data gap) memory: 592K\r\r\n"] 59 | [4.0216, "o", "[ 0.524367] x86/mm: Checked W+X mappings: passed, no W+X page"] 60 | [4.021687, "o", "s found.\r\r\n"] 61 | [4.021776, "o", "[ 0.524474] Run /sbin/init as init process\r\r\n"] 62 | [4.142783, "o", "[ 0.645547] Using default interface naming scheme 'v252'.\r\r\n"] 63 | [4.253767, "o", "\u001b7\u001b[999;999H\u001b[6n\u001b8"] 64 | [4.370896, "o", "[ 0.873384] quiz: starting user program\r\r\n"] 65 | [4.384132, "o", "[INFO tini (1)] Spawned child process '/bin/bash' with pid '511'\r\r\n"] 66 | [4.421358, "o", "bash: cannot set terminal process group (-1): Inappropriate ioctl for device\r\r\n"] 67 | [4.421711, "o", "bash: no job control in this shell\r\r\n"] 68 | [4.459765, "o", "\u001b[?2004h"] 69 | [4.45984, "o", "root@quiz:/# "] 70 | [5.902794, "o", "u"] 71 | [6.095481, "o", "n"] 72 | [6.211483, "o", "a"] 73 | [6.30866, "o", "m"] 74 | [6.452164, "o", "e"] 75 | [6.532543, "o", " "] 76 | [6.617359, "o", "-"] 77 | [6.719432, "o", "a"] 78 | [6.838828, "o", "\r\r\n\u001b[?2004l\r"] 79 | [6.848139, "o", "Linux quiz 5.10.170 #3 SMP Wed Jun 21 15:52:50 AEST 2023 x86_64 GNU/Linux\r\r\n"] 80 | [6.848846, "o", "\u001b[?2004hroot@quiz:/# "] 81 | [9.320781, "o", "d"] 82 | [9.456688, "o", "f"] 83 | [9.546923, "o", "\r\r\n\u001b[?2004l\r"] 84 | [9.558405, "o", "Filesystem 1K-blocks Used Available Use% Mounted on\r\r\noverlay 1018228 88 1018140 1% /"] 85 | [9.559016, "o", "\r\r\nnone 1015744 0 1015744 0% /dev\r\r\n"] 86 | [9.559324, "o", "\u001b[?2004hroot@quiz:/# "] 87 | [10.640303, "o", "u"] 88 | [10.811377, "o", "p"] 89 | [10.919079, "o", "t"] 90 | [11.031373, "o", "i"] 91 | [11.132613, "o", "m"] 92 | [11.257214, "o", "e"] 93 | [11.368075, "o", "\r\r\n\u001b[?2004l\r"] 94 | [11.415438, "o", " 12:47:56 up 0 min, 0 user, load average: 0.00, 0.00, 0.00\r\r\n"] 95 | [11.420134, "o", "\u001b[?2004h"] 96 | [11.420267, "o", "root@quiz:/# "] 97 | [14.714252, "o", "t"] 98 | [14.785298, "o", "o"] 99 | [14.848363, "o", "p"] 100 | [15.024741, "o", "\r\r\n\u001b[?2004l\r"] 101 | [15.104129, "o", "\u001b[?25l\u001b[?1c"] 102 | [15.261421, "o", "\u001b[H\u001b[J\u001b[m\u000ftop - 12:48:00 up 0 min, 0 user, load average: 0.00, 0.00, 0.00\u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K\r\r\nTasks:\u001b[m\u000f\u001b[39;49m\u001b[1m 49 \u001b[m\u000f\u001b[39;49mtotal,\u001b[m\u000f\u001b[39;49m\u001b[1m 1 \u001b[m\u000f\u001b[39;49mrunning,\u001b[m\u000f\u001b[39;49m\u001b[1m 48 \u001b[m\u000f\u001b[39;49msleeping,\u001b[m\u000f\u001b[39;49m\u001b[1m 0 \u001b[m\u000f\u001b[39;49mstopped,\u001b[m\u000f\u001b[39;49m\u001b[1m 0 \u001b[m\u000f\u001b[39;49mzombie\u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K"] 103 | [15.261834, "o", "\r\r\n%Cpu(s):\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mus,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49msy,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mni,\u001b[m\u000f\u001b[39;49m\u001b[1m100.0 \u001b[m\u000f\u001b[39;49mid,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mwa,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mhi,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49msi,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mst\u001b[m\u000f\u001b[39;49m\u001b[m\u000f \u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K"] 104 | [15.262111, "o", "\r\r\nMiB Mem :\u001b[m\u000f\u001b[39;49m\u001b[1m 1988.7 \u001b[m\u000f\u001b[39;49mtotal,\u001b[m\u000f\u001b[39;49m\u001b[1m 1909.8 \u001b[m\u000f\u001b[39;49mfree,\u001b[m\u000f\u001b[39;49m\u001b[1m 82.0 \u001b[m\u000f\u001b[39;49mused,\u001b[m\u000f\u001b[39;49m\u001b[1m 26.3 \u001b[m\u000f\u001b[39;49mbuff/cache\u001b[m\u000f\u001b[39;49m\u001b[m\u000f \u001b[m\u000f\u001b[39;49m\u001b[m\u000f \u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K\r\r\nMiB Swap:\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mtotal,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mfree,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mused.\u001b[m\u000f\u001b[39;49m\u001b[1m 1906.7 \u001b[m\u000f\u001b[39;49mavail Mem \u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[K"] 105 | [15.262378, "o", "\r\r\n\u001b[7m PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f\u001b[1m 515 root 20 0 8640 4560 2672 R 6.7 0.2 0:00.02 top \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 1 root 20 0 2472 904 820 S 0.0 0.0 0:00.07 tini \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 106 | [15.262644, "o", "\u001b[m\u000f 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 5 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 107 | [15.262832, "o", "\u001b[m\u000f 7 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/u+ \u001b["] 108 | [15.263026, "o", "m\u000f\u001b[39;49m\u001b[K\r\r\n"] 109 | [15.263235, "o", "\u001b[m\u000f 8 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks+ \u001b[m\u000f\u001b[39;49m\u001b[K"] 110 | [15.263394, "o", "\r\r\n\u001b[m\u000f 11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 111 | [15.263592, "o", "\u001b[m\u000f 12 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_sched \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 112 | [15.263783, "o", "\u001b[m\u000f 13 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 14 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 113 | [15.263937, "o", "\u001b[m\u000f 15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0 \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1 \u001b[m\u000f\u001b[39;49m\u001b[K"] 114 | [15.264074, "o", "\r\r\n\u001b[m\u000f 17 root rt 0 0 0 0 S 0.0 0.0 0:00.02 migration+ \u001b[m\u000f\u001b[39;49m\u001b[K"] 115 | [18.270077, "o", "\u001b[H\u001b[m\u000ftop - 12:48:03 up 0 min, 0 user, load average: 0.00, 0.00, 0.00\u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\r\r\n"] 116 | [18.270236, "o", "%Cpu(s):\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mus,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.2 \u001b[m\u000f\u001b[39;49msy,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mni,\u001b[m\u000f\u001b[39;49m\u001b[1m 99.8 \u001b[m\u000f\u001b[39;49mid,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mwa,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mhi,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49msi,\u001b[m\u000f\u001b[39;49m\u001b[1m 0.0 \u001b[m\u000f\u001b[39;49mst\u001b[m\u000f\u001b[39;49m\u001b[m\u000f \u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K\r\r\nMiB Mem :\u001b[m\u000f\u001b[39;49m\u001b[1m 1988.7 \u001b[m\u000f\u001b[39;49mtotal,\u001b[m\u000f\u001b[39;49m\u001b[1m 1909.7 \u001b[m\u000f\u001b[39;49mfree,\u001b[m\u000f\u001b[39;49m\u001b[1m 82.0 \u001b[m\u000f\u001b[39;49mused,\u001b[m\u000f\u001b[39;49m\u001b[1m 26.4 \u001b[m\u000f\u001b[39;49mbuff/cache\u001b[m\u000f\u001b[39;49m\u001b[m\u000f \u001b[m\u000f\u001b[39;49m\u001b[m\u000f \u001b[m\u000f\u001b[39;49m\u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\r\r\n\u001b[K"] 117 | [18.270336, "o", "\r\r\n\r\r\n\u001b[m\u000f 1 root 20 0 2472 904 820 S 0.0 0.0 0:00.07 tini \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp \u001b[m\u000f\u001b[39;49m\u001b[K"] 118 | [18.270404, "o", "\r\r\n\u001b[m\u000f 5 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/0+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 7 root 20 0 0 0 0 I 0.0 0.0 0:00.00 kworker/u+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 119 | [18.270474, "o", "\u001b[m\u000f 8 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 120 | [18.27051, "o", "\u001b[m\u000f 9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 121 | [18.270556, "o", "\u001b[m\u000f 11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 12 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_sched \u001b[m\u000f\u001b[39;49m\u001b[K"] 122 | [18.270596, "o", "\r\r\n\u001b[m\u000f 13 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 123 | [18.270633, "o", "\u001b[m\u000f 14 root 20 0 0 0"] 124 | [18.270692, "o", " 0 I 0.0 0.0 0:00.00 kworker/0+ \u001b[m\u000f\u001b[39;49m\u001b[K"] 125 | [18.270732, "o", "\r\r\n"] 126 | [18.270775, "o", "\u001b[m\u000f 15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0 \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1 \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n"] 127 | [18.270824, "o", "\u001b[m\u000f 17 root rt 0 0 0 0 S 0.0 0.0 0:00.02 migration+ \u001b[m\u000f\u001b[39;49m\u001b[K\r\r\n\u001b[m\u000f 18 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd+ \u001b[m\u000f\u001b[39;49m\u001b[K"] 128 | [19.964038, "o", "\u001b[26;1H\r\r\n\u001b[?25h\u001b[?0c\u001b[K"] 129 | [19.966092, "o", "\u001b[?2004hroot@quiz:/# "] 130 | [20.91514, "o", "\u001b[?2004l\r\r\r\n"] 131 | [20.915269, "o", "exit\r\r\n"] 132 | [20.915675, "o", "[INFO tini (1)] Main child exited normally (with status '0')\r\r\n"] 133 | [20.91574, "o", "[ 17.418076] K"] 134 | [20.915789, "o", "ernel panic - not syncing: Attempted to kill init! exitcode=0x00000000\r\r\n"] 135 | [20.915847, "o", "[ 17.418171] C"] 136 | [20.915899, "o", "PU: 1 PID: 1 Comm: tini Not tainted 5.10.170 #3\r\r\n[ 17.418251] Call Trace:\r\r\n"] 137 | [20.915946, "o", "[ 17.418305] dump_stack+0x57/"] 138 | [20.915995, "o", "0x6e\r\r\n"] 139 | [20.916035, "o", "[ 17.418359] panic+0x10e/0x2cc\r\r\n"] 140 | [20.91607, "o", "[ 17.418410] do_exit.cold+0xa"] 141 | [20.916091, "o", "7/0xb3\r\r\n[ 17.418460] do_group_exit+0x"] 142 | [20.916141, "o", "33/0xa0\r\r\n[ 17.418516] "] 143 | [20.916177, "o", "__x64_sys_exit_g"] 144 | [20.916222, "o", "roup+0x14/0x20\r\r\n[ 17.418563] do_syscall_64+0x30/0x40\r\r\n"] 145 | [20.916264, "o", "[ 17.418624] entry_SYSCALL_64"] 146 | [20.916312, "o", "_after_hwframe+0x61/0xc6\r\r\n"] 147 | [20.916353, "o", "[ 17.418698] RIP: 0033:0x7fb38"] 148 | [20.916391, "o", "bee6249\r\r\n[ 17.418745] Code: 00 4c 8b 05 b9 db 0f 00 be "] 149 | [20.91643, "o", "e7 00 00 00 ba 3c 00 00 00 eb 12 0f 1f 44 00 00 "] 150 | [20.916476, "o", "89 d0 0f 05 48 3"] 151 | [20.916515, "o", "d 00 f0 ff ff 77 1c f4 89 f0 0f 05 <48> 3d 00 f0 ff ff 76 e7 f7 "] 152 | [20.916556, "o", "d8 64 41 89 00 e"] 153 | [20.916599, "o", "b df 0f 1f 80 00 00 00\r\r\n"] 154 | [20.916633, "o", "[ 17.418963] RSP: 002b:00007ffe0aa86c28 EFLAGS"] 155 | [20.916698, "o", ": 00000246 ORIG_RAX: 00000000000000e7\r\r\n[ 17.419063] RAX: ffffffffffffffda RBX: 00007f"] 156 | [20.916745, "o", "b38bfe09e0 RCX: 00007fb38bee6249\r\r\n"] 157 | [20.916764, "o", "[ 17.419145] R"] 158 | [20.916776, "o", "DX: 000000000000"] 159 | [20.916853, "o", "003c RSI: 00000000000000e7 RDI: 0000000000000000\r\r\n"] 160 | [20.916869, "o", "[ 17.419237] RBP: 000000000000"] 161 | [20.91692, "o", "0000 R08: ffffffffffffff80 R09: 00007ffe0aa86b4f"] 162 | [20.916959, "o", "\r\r\n"] 163 | [20.916996, "o", "[ 17.419334] R10: 00007ffe0aa86ad0 R11: 0000000000000246 R12: "] 164 | [20.917059, "o", "00007fb38bfe09e0\r\r\n[ 17.419430] R13: 00007fb38bfe"] 165 | [20.917107, "o", "62e0 R14: 000000"] 166 | [20.917156, "o", "0000000001 R15: 00007fb38bfe62c8\r\r\n"] 167 | [21.019241, "o", "[quiz] 20230909-22:48:05 done\r\n"] 168 | [21.053059, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m⇡\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 169 | [23.538995, "o", "\u001b[?2004l\r\r\nexit\r\n"] 170 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | 375 | -------------------------------------------------------------------------------- /demo/quiz-tmux.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 106, "height": 28, "timestamp": 1736381034, "env": {"SHELL": "/bin/bash", "TERM": "xterm-kitty"}} 2 | [0.040647, "o", "\u001b]0;shell: ~/code/quiz\u0007"] 3 | [0.041004, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 4 | [0.36275, "o", "\u001b[H\u001b[2J\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 5 | [0.754085, "o", "#"] 6 | [0.929599, "o", " "] 7 | [1.01605, "o", "r"] 8 | [1.143507, "o", "e"] 9 | [1.237462, "o", "m"] 10 | [1.356048, "o", "e"] 11 | [1.413395, "o", "m"] 12 | [1.607468, "o", "b"] 13 | [1.662345, "o", "e"] 14 | [1.725277, "o", "r"] 15 | [1.797527, "o", " "] 16 | [1.925163, "o", "q"] 17 | [1.982145, "o", "u"] 18 | [2.060421, "o", "i"] 19 | [2.167217, "o", "z"] 20 | [2.352095, "o", ","] 21 | [2.445902, "o", " "] 22 | [2.680318, "o", "m"] 23 | [2.893234, "o", "y"] 24 | [3.186615, "o", " "] 25 | [3.393008, "o", "j"] 26 | [3.50405, "o", "a"] 27 | [3.59204, "o", "n"] 28 | [3.683199, "o", "k"] 29 | [4.380893, "o", "y"] 30 | [5.653306, "o", " "] 31 | [5.844205, "o", "k"] 32 | [5.889544, "o", "e"] 33 | [5.951604, "o", "r"] 34 | [6.036919, "o", "n"] 35 | [6.120594, "o", "e"] 36 | [6.209659, "o", "l"] 37 | [6.546875, "o", "+"] 38 | [6.765402, "o", "z"] 39 | [6.947756, "o", "f"] 40 | [7.076728, "o", "s"] 41 | [7.16705, "o", " "] 42 | [7.258411, "o", "d"] 43 | [7.366462, "o", "e"] 44 | [7.484878, "o", "v"] 45 | [7.557659, "o", " "] 46 | [7.764214, "o", "h"] 47 | [7.907241, "o", "e"] 48 | [8.027294, "o", "l"] 49 | [8.354363, "o", "p"] 50 | [8.439117, "o", "e"] 51 | [8.509986, "o", "r"] 52 | [8.714812, "o", "?"] 53 | [9.591121, "o", "\r\n\u001b[?2004l\r"] 54 | [9.593924, "o", "\u001b]0;shell: ~/code/quiz\u0007"] 55 | [9.609107, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 56 | [11.630781, "o", "\u001b[7m./quiz -p zfs,ztest /usr/local/share/zfs/zfs-tests.sh -DvKx -T removal\u001b[27m"] 57 | [12.880289, "o", "\r\u001b[C\u001b[C./quiz -p zfs,ztest /usr/local/share/zfs/zfs-tests.sh -DvKx -T removal "] 58 | [15.688831, "o", "|"] 59 | [16.470149, "o", " "] 60 | [16.539337, "o", "g"] 61 | [16.708626, "o", "r"] 62 | [16.823876, "o", "e"] 63 | [16.904638, "o", "p"] 64 | [17.013527, "o", " "] 65 | [17.175504, "o", "S"] 66 | [17.326126, "o", "U"] 67 | [17.421157, "o", "C"] 68 | [17.569735, "o", "C"] 69 | [17.711773, "o", "E"] 70 | [17.900394, "o", "S"] 71 | [18.058685, "o", "S"] 72 | [19.17415, "o", "\r\n\u001b[?2004l\r"] 73 | [19.187596, "o", "\u001b]0;./quiz -p zfs,ztest /usr/local/share/zfs/zfs-tests.sh -DvKx -T removal | grep SUCCESS\u0007"] 74 | [19.250461, "o", "[quiz] 20250109-11:04:14 matched release kernel image: 6.1.102\r\n"] 75 | [19.269479, "o", "[quiz] 20250109-11:04:14 using kernel: 6.1.102\r\n"] 76 | [19.272985, "o", "[quiz] 20250109-11:04:14 using rc: raw\r\n"] 77 | [19.330443, "o", "[quiz] 20250109-11:04:14 including profile: zfs\r\n"] 78 | [19.33587, "o", "[quiz] 20250109-11:04:14 including profile: ztest\r\n"] 79 | [19.386544, "o", "[quiz] 20250109-11:04:14 creating run script\r\n"] 80 | [19.392467, "o", "[quiz] 20250109-11:04:14 starting microvm\r\n"] 81 | [23.949407, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool create -f testpool loop0 loop1 loop2\r\r\n"] 82 | [23.99061, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zfs create testpool/testfs\r\r\n"] 83 | [24.022198, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zfs set mountpoint=/var/tmp/testdir testpool/testfs\r\r\n"] 84 | [24.04073, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool remove testpool loop1\r\r\n"] 85 | [24.052792, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool wait -t remove testpool\r\r\n"] 86 | [24.061358, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool sync testpool\r\r\n"] 87 | [24.0727, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: is_pool_removed testpool\r\r\n"] 88 | [24.07512, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: wait_for_removal testpool\r\r\n"] 89 | [24.09226, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: vdevs_in_pool testpool loop1 exited 1\r\r\n"] 90 | [24.120365, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool remove testpool loop2\r\r\n"] 91 | [24.136517, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool wait -t remove testpool\r\r\n"] 92 | [24.151924, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool sync testpool\r\r\n"] 93 | [24.17064, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: is_pool_removed testpool\r\r\n"] 94 | [24.175223, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: wait_for_removal testpool\r\r\n"] 95 | [24.199519, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: vdevs_in_pool testpool loop2 exited 1\r\r\n"] 96 | [24.217397, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: [ xloop0 = xloop0 ]\r\r\n"] 97 | [24.233118, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool remove testpool loop2 exited 1\r\r\n"] 98 | [24.385219, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool destroy -f testpool\r\r\n"] 99 | [24.413838, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: rm -rf /var/tmp/testdir\r\r\n"] 100 | [24.51382, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool create -f testpool loop0\r\r\n"] 101 | [24.538741, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zfs create testpool/testfs\r\r\n"] 102 | [24.573845, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zfs set mountpoint=/var/tmp/testdir testpool/testfs\r\r\n"] 103 | [24.577684, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: default_setup_noexit loop0\r\r\n"] 104 | [24.586279, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: mkfile -n 1g //var/tmp/testdir/00\r\r\n"] 105 | [26.278992, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: randwritecomp //var/tmp/testdir/00 25000\r\r\n"] 106 | [26.325366, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool add -f testpool loop2\r\r\n"] 107 | [26.327629, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: set_tunable32 REMOVAL_SUSPEND_PROGRESS 1\r\r\n"] 108 | [26.353153, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool remove testpool loop0\r\r\n"] 109 | [26.36852, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool status testpool\r\r\n"] 110 | [27.382554, "o", "\u001b[01;31m\u001b[KSUCCESS\u001b[m\u001b[K: zpool remove -s testpool\r\r\n"] 111 | [28.918906, "o", "[quiz] 20250109-11:04:23 done\r\n"] 112 | [28.920968, "o", "\u001b]0;shell: ~/code/quiz\u0007"] 113 | [28.937493, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 114 | [32.14024, "o", "#"] 115 | [32.40039, "o", " "] 116 | [32.544803, "o", "a"] 117 | [32.634236, "o", "n"] 118 | [32.806566, "o", "y"] 119 | [32.844038, "o", "w"] 120 | [33.011027, "o", "a"] 121 | [33.060862, "o", "y"] 122 | [33.328481, "o", ","] 123 | [33.441959, "o", " "] 124 | [33.741421, "o", "i"] 125 | [33.834524, "o", "t"] 126 | [33.936982, "o", " "] 127 | [34.04358, "o", "g"] 128 | [34.116199, "o", "o"] 129 | [34.227582, "o", "t"] 130 | [34.307874, "o", " "] 131 | [34.408181, "o", "a"] 132 | [34.459275, "o", " "] 133 | [34.599786, "o", "n"] 134 | [34.638137, "o", "e"] 135 | [34.735508, "o", "w"] 136 | [34.856054, "o", " "] 137 | [34.984439, "o", "t"] 138 | [35.137612, "o", "r"] 139 | [35.21713, "o", "i"] 140 | [35.326687, "o", "c"] 141 | [35.406577, "o", "k"] 142 | [35.587425, "o", " "] 143 | [35.734437, "o", "t"] 144 | [35.81459, "o", "o"] 145 | [35.912009, "o", "d"] 146 | [36.036025, "o", "a"] 147 | [36.076651, "o", "y"] 148 | [36.28041, "o", "."] 149 | [36.405041, "o", " "] 150 | [36.568156, "o", "n"] 151 | [36.697454, "o", "o"] 152 | [36.78908, "o", "w"] 153 | [36.906474, "o", " "] 154 | [37.500212, "o", "i"] 155 | [37.554531, "o", "f"] 156 | [37.653529, "o", " "] 157 | [38.226626, "o", "i"] 158 | [38.264251, "o", "t"] 159 | [38.386904, "o", " "] 160 | [38.666703, "o", "s"] 161 | [38.868561, "o", "e"] 162 | [39.008343, "o", "e"] 163 | [39.189478, "o", "s"] 164 | [39.310208, "o", " "] 165 | [39.428555, "o", "y"] 166 | [39.515376, "o", "o"] 167 | [39.577962, "o", "u"] 168 | [41.777822, "o", "'"] 169 | [41.838013, "o", "r"] 170 | [41.962655, "o", "e"] 171 | [42.011479, "o", " "] 172 | [42.088445, "o", "o"] 173 | [42.236337, "o", "n"] 174 | [42.340473, "o", " "] 175 | [42.519113, "o", "a"] 176 | [42.570611, "o", " "] 177 | [42.761712, "o", "t"] 178 | [42.885191, "o", "e"] 179 | [42.94082, "o", "r"] 180 | [43.003223, "o", "m"] 181 | [43.210524, "o", "i"] 182 | [43.352192, "o", "a"] 183 | [43.972312, "o", "\b\u001b[K"] 184 | [44.163815, "o", "n"] 185 | [44.247864, "o", "a"] 186 | [44.349319, "o", "l"] 187 | [44.448261, "o", " "] 188 | [44.560093, "o", "a"] 189 | [44.632541, "o", "n"] 190 | [44.726175, "o", "d"] 191 | [44.815073, "o", " "] 192 | [45.0817, "o", "y"] 193 | [45.240685, "o", "o"] 194 | [45.286233, "o", "u"] 195 | [45.446954, "o", "'"] 196 | [45.523691, "o", "r"] 197 | [45.626017, "o", "e"] 198 | [45.700141, "o", " "] 199 | [45.843423, "o", "n"] 200 | [45.974017, "o", "o"] 201 | [46.075741, "o", "t"] 202 | [46.161908, "o", " "] 203 | [46.653262, "o", "s"] 204 | [46.817041, "o", "e"] 205 | [46.896196, "o", "n"] 206 | [46.985639, "o", "d"] 207 | [47.043662, "o", "i"] 208 | [47.144191, "o", "n"] 209 | [47.214263, "o", "g"] 210 | [47.310222, "o", " "] 211 | [47.37864, "o", "o"] 212 | [47.456704, "o", "u"] 213 | [47.555635, "o", "t"] 214 | [47.860069, "o", "p"] 215 | [47.984124, "o", "u"] 216 | [48.112458, "o", "t"] 217 | [48.228192, "o", " "] 218 | [48.989971, "o", "a"] 219 | [49.03203, "o", "n \r"] 220 | [49.202048, "o", "y"] 221 | [49.300079, "o", "w"] 222 | [49.387742, "o", "h"] 223 | [49.496174, "o", "e"] 224 | [49.567539, "o", "r"] 225 | [49.68753, "o", "e"] 226 | [49.799879, "o", " "] 227 | [49.940228, "o", "("] 228 | [50.157351, "o", "l"] 229 | [50.258907, "o", "i"] 230 | [50.440418, "o", "k"] 231 | [50.486054, "o", "e"] 232 | [50.612436, "o", " "] 233 | [50.719729, "o", "I"] 234 | [50.830207, "o", " "] 235 | [51.167097, "o", "j"] 236 | [51.316013, "o", "u"] 237 | [51.361428, "o", "s"] 238 | [51.423964, "o", "t"] 239 | [51.517745, "o", " "] 240 | [51.604716, "o", "w"] 241 | [51.758303, "o", "a"] 242 | [51.821312, "o", "s"] 243 | [52.236129, "o", " "] 244 | [52.321488, "o", "w"] 245 | [52.406281, "o", "i"] 246 | [52.476992, "o", "t"] 247 | [52.566113, "o", "h"] 248 | [52.659557, "o", " "] 249 | [52.714378, "o", "g"] 250 | [52.861141, "o", "r"] 251 | [52.964498, "o", "e"] 252 | [53.089746, "o", "p"] 253 | [53.299563, "o", ")"] 254 | [53.717415, "o", ","] 255 | [53.823861, "o", " "] 256 | [54.04215, "o", "i"] 257 | [54.180423, "o", "t"] 258 | [54.244271, "o", "'"] 259 | [54.432938, "o", "l"] 260 | [54.616235, "o", "l"] 261 | [54.778765, "o", " "] 262 | [55.057578, "o", "l"] 263 | [55.253857, "o", "o"] 264 | [55.290251, "o", "a"] 265 | [55.37607, "o", "d"] 266 | [55.475424, "o", " "] 267 | [55.591652, "o", "u"] 268 | [55.743524, "o", "p"] 269 | [55.861367, "o", " "] 270 | [56.078071, "o", "i"] 271 | [56.196524, "o", "n"] 272 | [56.30799, "o", " "] 273 | [56.657337, "o", "t"] 274 | [56.705582, "o", "m"] 275 | [56.873385, "o", "u"] 276 | [56.940801, "o", "x"] 277 | [57.031461, "o", " "] 278 | [57.117373, "o", "i"] 279 | [57.17763, "o", "n"] 280 | [57.230842, "o", "s"] 281 | [57.346312, "o", "t"] 282 | [57.485014, "o", "e"] 283 | [57.628238, "o", "a"] 284 | [57.700176, "o", "d"] 285 | [58.094373, "o", "\r\n\u001b[?2004l\r"] 286 | [58.096714, "o", "\u001b]0;shell: ~/code/quiz\u0007"] 287 | [58.108966, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 288 | [59.138687, "o", "# anyway, it got a new trick today. now if it sees you're on a terminal and you're not sending output anywhere (like I just was with grep), it'll load up in tmux instead"] 289 | [60.03597, "o", "\u001b[A\r\u001b[C\u001b[C\u001b[19P./quiz -p zfs,ztest /usr/local/share/zfs/zfs-tests.sh -DvKx -T removal | grep SUCCESS\r\n\r\u001b[K\u001b[A\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C"] 290 | [63.088188, "o", "\b\b\b\b\b\b\b\u001b[K"] 291 | [63.311016, "o", "\b\b\b\b\b\u001b[K"] 292 | [63.500492, "o", "\b\b\u001b[K"] 293 | [63.666769, "o", "\b\b\b\b\b\b\b\b\u001b[K"] 294 | [63.848814, "o", "\b\b\b\u001b[K"] 295 | [64.022647, "o", "\b\b\b\b\b\b\u001b[K"] 296 | [64.205644, "o", "\r\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[K"] 297 | [64.394595, "o", "\b\b\b\b\b\b\b\b\b\b\u001b[K"] 298 | [65.004595, "o", "z"] 299 | [65.199693, "o", "f"] 300 | [65.323092, "o", "s"] 301 | [66.074699, "o", ","] 302 | [66.344723, "o", "m"] 303 | [66.390573, "o", "e"] 304 | [66.505641, "o", "m"] 305 | [66.626353, "o", "d"] 306 | [66.735466, "o", "e"] 307 | [66.918807, "o", "v"] 308 | [67.04232, "o", " "] 309 | [67.128859, "o", "s"] 310 | [67.284905, "o", "a"] 311 | [67.32565, "o", "n"] 312 | [67.427836, "o", "i"] 313 | [67.553108, "o", "t"] 314 | [67.703824, "o", "y"] 315 | [67.875137, "o", "\r\n\u001b[?2004l\r"] 316 | [67.887518, "o", "\u001b]0;./quiz -p zfs,memdev sanity\u0007"] 317 | [67.960114, "o", "[quiz] 20250109-11:05:02 matched release kernel image: 6.1.102\r\n"] 318 | [67.983081, "o", "[quiz] 20250109-11:05:02 using kernel: 6.1.102\r\n"] 319 | [67.988056, "o", "[quiz] 20250109-11:05:02 using rc: tmux\r\n"] 320 | [68.049108, "o", "[quiz] 20250109-11:05:03 including profile: zfs\r\n"] 321 | [68.053869, "o", "[quiz] 20250109-11:05:03 including profile: memdev\r\n"] 322 | [68.106443, "o", "[quiz] 20250109-11:05:03 creating run script\r\n"] 323 | [68.11309, "o", "[quiz] 20250109-11:05:03 starting microvm\r\n"] 324 | [68.778995, "o", "[ 0.125335] loop: module loaded\r\r\n[ 0.125435] virtio_blk virtio2: 1/0/0 default/read/poll queues\r\r\n"] 325 | [68.779365, "o", "[ 0.125793] virtio_blk virtio2: [vda] 1655844 512-byte logical blocks (848 MB/809 MiB)\r\r\n"] 326 | [68.779912, "o", "[ 0.126349] i8042: PNP: No PS/2 controller found.\r\r\n"] 327 | [68.780121, "o", "[ 0.126615] d"] 328 | [68.780134, "o", "evice-mapper: io"] 329 | [68.780142, "o", "ctl: 4.47.0-ioct"] 330 | [68.780151, "o", "l (2022-07-28) i"] 331 | [68.780239, "o", "nitialised: dm-devel@redhat.com\r"] 332 | [68.78026, "o", "\r\n"] 333 | [68.780535, "o", "[ 0.126985] NET: Registered PF_PACKET protocol family\r\r\n"] 334 | [68.780577, "o", "[ 0.127068] 9"] 335 | [68.780586, "o", "pnet: Installing 9P2000 support\r"] 336 | [68.780634, "o", "\r\n"] 337 | [68.781526, "o", "[ 0.127978] NET: Registered PF_VSOCK protocol family\r\r\n[ 0.128028] IPI shorthand bro"] 338 | [68.781551, "o", "adcast: enabled\r\r\n"] 339 | [68.781563, "o", "[ 0.128059] AVX2 version of g"] 340 | [68.78158, "o", "cm_enc/dec engaged.\r\r\n"] 341 | [68.78179, "o", "[ 0.128257] A"] 342 | [68.781895, "o", "ES CTR mode by8 optimization enabled\r\r\n"] 343 | [68.78286, "o", "[ 0.129306] sched_clock: Marking stable (125585676, 3705364)-"] 344 | [68.78293, "o", ">(136993170, -7702130)\r\r\n"] 345 | [68.783326, "o", "[ 0.129810] r"] 346 | [68.78338, "o", "egistered taskst"] 347 | [68.783421, "o", "ats version 1\r\r\n[ 0.129871] Loading compiled-in X.509 certificates\r\r\n"] 348 | [68.948081, "o", "[ 0.294372] clk: Disabling unused clocks\r\r\n"] 349 | [68.949312, "o", "[ 0.295728] EXT4-fs (vda): mounting ext2 file system using the ext4 subsystem\r\r\n"] 350 | [68.950109, "o", "[ 0.296372] EXT4-fs (vda): mounted filesystem without journal. Quota mode: none.\r\r\n[ 0.296515] VFS: Mounted root (ext2 filesystem) readonly on d"] 351 | [68.950162, "o", "evice 254:0.\r\r\n"] 352 | [68.952646, "o", "[ 0.298897] Freeing unused kernel image (initmem) memory: 2368K\r\r\n[ 0.299032] Write protecting the kernel read-only data: 18432k\r\r\n"] 353 | [68.953283, "o", "[ 0.299642] Freeing unused kernel image (text/rodata gap) memory: 2040K\r\r\n"] 354 | [68.953583, "o", "[ 0.299969] Freeing unused kernel image (rodata/data gap) mem"] 355 | [68.953631, "o", "ory: 264K\r\r\n"] 356 | [68.953986, "o", "[ 0.300355] x86/mm: Checked W+X mappings: passed, no W+X pages found.\r\r\n[ 0.300489] R"] 357 | [68.954109, "o", "un /sbin/init as init process\r\r\n"] 358 | [69.116967, "o", "[ 0.463361] Using default interface naming scheme 'v252'.\r\r\n"] 359 | [69.259621, "o", "\u001b7\u001b[999;999H\u001b[6n\u001b8"] 360 | [69.37724, "o", "[ 0.723579] quiz: starting profile init: zfs\r\r\n"] 361 | [69.416215, "o", "[ 0.762491] spl: loading out-of-tree module taints kernel.\r\r\n"] 362 | [69.718417, "o", "[ 1.064670] zfs: module license 'CDDL' taints kernel.\r\r\n[ 1.064799] Disabling lock debugging due to kernel taint\r\r\n"] 363 | [70.953986, "o", "[ 2.300315] ZFS: Loaded module v2.3.99-157_gb8e09c7007 (DEBUG mode), ZFS pool version 5000, ZFS filesystem version 5\r\r\n"] 364 | [70.955187, "o", "[ 2.301458] quiz: starting profile init: memdev\r\r\n"] 365 | [70.984541, "o", "[ 2.330950] loop0: detected capacity change from 0 to 204800\r\r\n"] 366 | [70.984778, "o", "[ 2.331258] quiz: memdev: created quizm0\r\r\n"] 367 | [71.01634, "o", "[ 2.362726] loop1: detected capacity change from 0 to 204800\r\r\n"] 368 | [71.016492, "o", "[ 2.362981] quiz: memdev: created quizm1\r\r\n"] 369 | [71.043298, "o", "[ 2.389471] loop2: detected capacity change from 0 to 204800\r\r\n"] 370 | [71.043557, "o", "[ 2.389830] quiz: memdev: created quizm2\r\r\n"] 371 | [71.067274, "o", "[ 2.413539] loop3: detected capacity change from 0 to 204800\r\r\n"] 372 | [71.067472, "o", "[ 2.413857] quiz: memdev: created quizm3\r\r\n"] 373 | [71.096058, "o", "[ 2.442401] loop4: detected capacity change from 0 to 204800\r\r\n"] 374 | [71.096138, "o", "[ 2.442658] q"] 375 | [71.096169, "o", "uiz: memdev: created quizm4\r\r\n"] 376 | [71.125027, "o", "[ 2.471307] loop5: detected capacity change from 0 to 204800\r\r\n"] 377 | [71.125247, "o", "[ 2.471687] quiz: memdev: created quizm5\r\r\n"] 378 | [71.129407, "o", "[INFO tini (1)] Spawned child process '/bin/sh' with pid '505'\r\r\n"] 379 | [71.196729, "o", "\u001b[H\u001b[J\u001b[?25h\u001b[?0c\u001b[?1000l\u001b[?1002l\u001b[?1003l\u001b[?1006l\u001b[?1005l\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[?1006l\u001b[?1000l\u001b[?1002l\u001b[?1003l\u001b[?2004l\u001b[1;1H\u001b[1;28r\u001b[>c\u001b[>q\u001b[1;1H"] 380 | [71.197476, "o", "\u001b[?25l\u001b[?1c\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg- 1:run* \"quiz\" 00:05 09-Jan-25\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[1;1H\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[?1006l\u001b[?1000l\u001b[?1002l\u001b[?1003l\u001b[?2004l\u001b[1;1H\u001b[1;28r"] 381 | [71.197712, "o", "\u001b[?25l\u001b[?1c\u001b[1;1H\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg- 1:run* \"quiz\" 00:05 09-Jan-25\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[1;1H"] 382 | [71.200157, "o", "\u001b[?7727h\u001b[?7727h"] 383 | [71.201294, "o", "\u001b[32m[ 2.547345] \u001b[33mquiz: \u001b[39m\u001b[1mstarting user program\r\r\n\u001b[m\u000f"] 384 | [71.204647, "o", "+ sysctl kernel.hung_task_timeout_secs=10\r\r\n"] 385 | [71.207374, "o", "kernel.hung_task_timeout_secs = 10\r\r\n"] 386 | [71.207475, "o", "+ zpool create tank raidz1 quizm0 quizm1 quizm2 quizm3\r\r\n"] 387 | [71.303228, "o", "+ fio --directory=/tank --name=sanity --ioengine=pvsync2 --rw=randrw --nrfiles=16 --filesize=1M --runtime=10 --time_based --numjobs=8 --group_reporting --fsync=1\r\r\n"] 388 | [71.470869, "o", "sanity: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=pvsync2, iodepth=1\r\r\n"] 389 | [71.473016, "o", "...\r\r\nfio-3.33\r\r\n"] 390 | [71.539403, "o", "Starting 8 processes\r\r\nsanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 391 | [71.632671, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 392 | [71.75725, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 393 | [71.870827, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 394 | [72.004132, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 395 | [72.169454, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 396 | [72.330576, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 397 | [72.532741, "o", "sanity: Laying out IO files (16 files / total 16MiB)\r\r\n"] 398 | [82.0387, "o", "Jobs: 8 (f=128)\r"] 399 | [83.037974, "o", "Jobs: 8 (f=128)\r"] 400 | [84.038337, "o", "Jobs: 8 (f=128): [m(8)][30.0%][r=2508KiB/s,w=2872KiB/s][r=627,w=718 IOPS][eta 00m:07s]\r"] 401 | [85.039008, "o", "Jobs: 8 (f=128): [m(8)][40.0%][r=2904KiB/s,w=3048KiB/s][r=726,w=762 IOPS][eta 00m:06s]\r"] 402 | [86.038192, "o", "Jobs: 8 (f=128): [m(8)][50.0%][r=2882KiB/s,w=2994KiB/s][r=720,w=748 IOPS][eta 00m:05s]\r"] 403 | [87.038577, "o", "Jobs: 8 (f=128): [m(8)][60.0%][r=2676KiB/s,w=2892KiB/s][r=669,w=723 IOPS][eta 00m:04s]\r"] 404 | [88.037764, "o", "Jobs: 8 (f=128): [m(8)][70.0%][r=2734KiB/s,w=2890KiB/s][r=683,w=722 IOPS][eta 00m:03s]\r"] 405 | [89.038069, "o", "Jobs: 8 (f=128): [m(8)][80.0%][r=2704KiB/s,w=2912KiB/s][r=676,w=728 IOPS][eta 00m:02s]\r"] 406 | [90.038335, "o", "Jobs: 8 (f=128): [m(8)][90.0%][r=2684KiB/s,w=2660KiB/s][r=671,w=665 IOPS][eta 00m:01s]\r"] 407 | [90.091794, "o", "\u001b[?25l\u001b[?1c\u001b[32m\u001b[H[ 0.300538] \u001b[39m with arguments:\u001b[K\u001b[32m\r\r\n[ 0.300539] \u001b[39m /sbin/init\u001b[K\u001b[32m\r\r\n[ 0.300539] \u001b[39m with environment:\u001b[K\u001b[32m\r\r\n[ 0.300539] \u001b[39m HOME=/\u001b[K\u001b[32m\r\r\n[ 0.300540] \u001b[39m TERM=linux\u001b[K\u001b[32m\r\r\n[ 0.463361] \u001b[39m\u001b[1mUsing default interface naming scheme 'v252'.\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 0.723579] \u001b[33mquiz: \u001b[39m\u001b[1mstarting profile init: zfs\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 0.762491] \u001b[33mspl: \u001b[39m\u001b[1mloading out-of-tree module taints kernel.\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 1.064670] \u001b[33mzfs: \u001b[39m\u001b[1mmodule license 'CDDL' taints kernel.\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 1.064799] \u001b[39m\u001b[1mDisabling lock debugging due to kernel taint\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.300315] \u001b[33mZFS: \u001b[39mLoaded module v2.3.99-157_gb8e09c7007 (DEBUG mode), ZFS pool version 5000, ZFS filesystem version 5\u001b[K\u001b[32m\r\r\n[ 2.301458] \u001b[33mquiz: \u001b[39m\u001b[1mstarting profile init: memdev\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.330950] \u001b[33mloop0: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.331258] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quiz"] 408 | [90.091824, "o", "m0\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.362726] \u001b[33mloop1: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.362981] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm1\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.389471] \u001b[33mloop2: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.389830] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm2\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.413539] \u001b[33mloop3: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.413857] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm3\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.442401] \u001b[33mloop4: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.442658] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm4\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.471307] \u001b[33mloop5: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.471687] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm5\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.547345] \u001b[33mquiz: \u001b[39m\u001b[1mstarting user program\u001b[m\u000f\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg* 1:run- \"quiz\" 00:05 09-Jan-25\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[27;1H"] 409 | [91.44177, "o", "\u001b[?25l\u001b[?1c\u001b[30m\u001b[43m\r\r\n:\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;2H"] 410 | [92.200947, "o", "\u001b[30m\u001b[43m\r:k\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;3H"] 411 | [92.253681, "o", "\u001b[30m\u001b[43m\r:ke\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;4H"] 412 | [92.301383, "o", "\u001b[30m\u001b[43m\r:ker\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;5H"] 413 | [92.393562, "o", "\u001b[30m\u001b[43m\r:kern\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;6H"] 414 | [92.457171, "o", "\u001b[30m\u001b[43m\r:kerne\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;7H"] 415 | [92.551804, "o", "\u001b[30m\u001b[43m\r:kernel\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;8H"] 416 | [92.663485, "o", "\u001b[30m\u001b[43m\r:kernel \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;9H"] 417 | [92.861973, "o", "\u001b[30m\u001b[43m\r:kernel u\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;10H"] 418 | [92.956271, "o", "\u001b[30m\u001b[43m\r:kernel ut\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;11H"] 419 | [93.115393, "o", "\u001b[30m\u001b[43m\r:kernel utp\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;12H"] 420 | [93.483215, "o", "\u001b[30m\u001b[43m\r:kernel ut\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;11H"] 421 | [93.690724, "o", "\u001b[30m\u001b[43m\r:kernel u\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;10H"] 422 | [93.825655, "o", "\u001b[30m\u001b[43m\r:kernel \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;9H"] 423 | [93.981028, "o", "\u001b[30m\u001b[43m\r:kernel o\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;10H"] 424 | [94.059697, "o", "\u001b[30m\u001b[43m\r:kernel ou\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;11H"] 425 | [94.204142, "o", "\u001b[30m\u001b[43m\r:kernel out\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;12H"] 426 | [94.28299, "o", "\u001b[30m\u001b[43m\r:kernel outp\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;13H"] 427 | [94.408451, "o", "\u001b[30m\u001b[43m\r:kernel outpu\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;14H"] 428 | [94.534722, "o", "\u001b[30m\u001b[43m\r:kernel output\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;15H"] 429 | [94.628502, "o", "\u001b[30m\u001b[43m\r:kernel output \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;16H"] 430 | [94.757555, "o", "\u001b[30m\u001b[43m\r:kernel output o\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;17H"] 431 | [94.89942, "o", "\u001b[30m\u001b[43m\r:kernel output ov\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;18H"] 432 | [95.05315, "o", "\u001b[30m\u001b[43m\r:kernel output ove\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;19H"] 433 | [95.109275, "o", "\u001b[30m\u001b[43m\r:kernel output over\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;20H"] 434 | [95.194294, "o", "\u001b[30m\u001b[43m\r:kernel output over \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;21H"] 435 | [95.307583, "o", "\u001b[30m\u001b[43m\r:kernel output over h\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;22H"] 436 | [95.354833, "o", "\u001b[30m\u001b[43m\r:kernel output over he\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;23H"] 437 | [95.793426, "o", "\u001b[30m\u001b[43m\r:kernel output over her\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;24H"] 438 | [96.165034, "o", "\u001b[30m\u001b[43m\r:kernel output over here\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;25H"] 439 | [96.4443, "o", "\u001b[30m\u001b[43m\r:kernel output over here!\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;26H"] 440 | [97.19806, "o", "\u001b[32m\u001b[H[ 0.300538] \u001b[39m with arguments:\u001b[K\u001b[32m\r\r\n[ 0.300539] \u001b[39m /sbin/init\u001b[K\u001b[32m\r\r\n[ 0.300539] \u001b[39m with environment:\u001b[K\u001b[32m\r\r\n[ 0.300539] \u001b[39m HOME=/\u001b[K\u001b[32m\r\r\n[ 0.300540] \u001b[39m TERM=linux\u001b[K\u001b[32m\r\r\n[ 0.463361] \u001b[39m\u001b[1mUsing default interface naming scheme 'v252'.\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 0.723579] \u001b[33mquiz: \u001b[39m\u001b[1mstarting profile init: zfs\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 0.762491] \u001b[33mspl: \u001b[39m\u001b[1mloading out-of-tree module taints kernel.\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 1.064670] \u001b[33mzfs: \u001b[39m\u001b[1mmodule license 'CDDL' taints kernel.\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 1.064799] \u001b[39m\u001b[1mDisabling lock debugging due to kernel taint\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.300315] \u001b[33mZFS: \u001b[39mLoaded module v2.3.99-157_gb8e09c7007 (DEBUG mode), ZFS pool version 5000, ZFS filesystem version 5\u001b[K\u001b[32m\r\r\n[ 2.301458] \u001b[33mquiz: \u001b[39m\u001b[1mstarting profile init: memdev\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.330950] \u001b[33mloop0: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.331258] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm0\u001b[m\u000f\u001b[K\u001b["] 441 | [97.198113, "o", "32m\r\r\n[ 2.362726] \u001b[33mloop1: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.362981] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm1\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.389471] \u001b[33mloop2: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.389830] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm2\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.413539] \u001b[33mloop3: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.413857] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm3\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.442401] \u001b[33mloop4: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.442658] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm4\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.471307] \u001b[33mloop5: \u001b[39mdetected capacity change from 0 to 204800\u001b[K\u001b[32m\r\r\n[ 2.471687] \u001b[33mquiz: \u001b[39m\u001b[1mmemdev: created quizm5\u001b[m\u000f\u001b[K\u001b[32m\r\r\n[ 2.547345] \u001b[33mquiz: \u001b[39m\u001b[1mstarting user program\u001b[m\u000f\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg* 1:run- \"quiz\" 00:05 09-Jan-25\u001b[m\u000f\u001b[27;1H\u001b[?25h\u001b[?0c"] 442 | [99.175887, "o", "\u001b[?25l\u001b[?1c\u001b[1;8H\u001b[1K\u001b[C quizm2 ONLINE 0 0 0\u001b[K\u001b[2;8H\u001b[1K\u001b[C quizm3 ONLINE 0 0 0\u001b[K\r\r\n\u001b[K\r\r\nerrors: No known data errors\u001b[K\r\r\n+ zpool export -a\u001b[K\r\r\n+ zpool import -a\u001b[K\r\r\n+ zpool scrub -w tank\u001b[K\r\r\n+ zpool status -v\u001b[K\r\r\n pool: tank\u001b[K\r\r\n state: ONLINE\u001b[K\r\r\n scan: scrub repaired 0B in 00:00:00 with 0 errors on Thu Jan 9 00:05:26 2025\u001b[K\r\r\nconfig:\u001b[K\r\r\n\u001b[K\u001b[14;8H\u001b[1K\u001b[CNAME STATE READ WRITE CKSUM\u001b[K\u001b[15;8H\u001b[1K\u001b[Ctank ONLINE 0 0 0\u001b[K\u001b[16;8H\u001b[1K\u001b[C raidz1-0 ONLINE 0 0 0\u001b[K\u001b[17;8H\u001b[1K\u001b[C quizm0 ONLINE 0 0 0\u001b[K\u001b[18;8H\u001b[1K\u001b[C quizm1 ONLINE 0 0 0\u001b[K\u001b[19;8H\u001b[1K\u001b[C quizm2 ONLINE 0 0 0\u001b[K\u001b[20;8H\u001b[1K\u001b[C quizm3 ONLINE 0 0 0\u001b[K\r\r\n\u001b[K\r\r\nerrors: No known data errors\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n[quiz run finished. Ctrl-C or detach session to exit]\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg- 1:run* \"quiz\" 00:05 09"] 443 | [99.175943, "o", "-Jan-25\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[27;1H"] 444 | [103.168531, "o", "\u001b[?25l\u001b[?1c\u001b[30m\u001b[43m\r\r\n:\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;2H"] 445 | [103.756356, "o", "\u001b[30m\u001b[43m\r:c\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;3H"] 446 | [103.83571, "o", "\u001b[30m\u001b[43m\r:ch\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;4H"] 447 | [103.929324, "o", "\u001b[30m\u001b[43m\r:che\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;5H"] 448 | [104.091762, "o", "\u001b[30m\u001b[43m\r:chee\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;6H"] 449 | [104.193582, "o", "\u001b[30m\u001b[43m\r:cheek\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;7H"] 450 | [104.38507, "o", "\u001b[30m\u001b[43m\r:cheekl\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;8H"] 451 | [104.88273, "o", "\u001b[30m\u001b[43m\r:cheek\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;7H"] 452 | [105.025756, "o", "\u001b[30m\u001b[43m\r:cheeky\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;8H"] 453 | [105.177616, "o", "\u001b[30m\u001b[43m\r:cheeky \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;9H"] 454 | [105.33088, "o", "\u001b[30m\u001b[43m\r:cheeky l\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;10H"] 455 | [105.402254, "o", "\u001b[30m\u001b[43m\r:cheeky li\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;11H"] 456 | [105.569086, "o", "\u001b[30m\u001b[43m\r:cheeky lil\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;12H"] 457 | [106.056562, "o", "\u001b[30m\u001b[43m\r:cheeky lil \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;13H"] 458 | [106.202678, "o", "\u001b[30m\u001b[43m\r:cheeky lil p\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;14H"] 459 | [106.329106, "o", "\u001b[30m\u001b[43m\r:cheeky lil pa\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;15H"] 460 | [106.426619, "o", "\u001b[30m\u001b[43m\r:cheeky lil pau\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;16H"] 461 | [106.564079, "o", "\u001b[30m\u001b[43m\r:cheeky lil paus\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;17H"] 462 | [106.840424, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;18H"] 463 | [107.535064, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;19H"] 464 | [107.640817, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause w\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;20H"] 465 | [107.720257, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause wh\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;21H"] 466 | [107.83402, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause whe\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;22H"] 467 | [107.913485, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;23H"] 468 | [107.99878, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;24H"] 469 | [108.527076, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when i\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;25H"] 470 | [108.572244, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when it\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;26H"] 471 | [108.729592, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when its\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;27H"] 472 | [108.831511, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when its \u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;28H"] 473 | [108.925938, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when its d\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;29H"] 474 | [108.997856, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when its do\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;30H"] 475 | [109.136631, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when its don\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;31H"] 476 | [109.215353, "o", "\u001b[30m\u001b[43m\r:cheeky lil pause when its done\u001b[7m \u001b[m\u000f\u001b[30m\u001b[43m \u001b[m\u000f\u001b[28;32H"] 477 | [111.264172, "o", "\u001b[1;8H\u001b[1K\u001b[C quizm2 ONLINE 0 0 0\u001b[K\u001b[2;8H\u001b[1K\u001b[C quizm3 ONLINE 0 0 0\u001b[K\r\r\n\u001b[K\r\r\nerrors: No known data errors\u001b[K\r\r\n+ zpool export -a\u001b[K\r\r\n+ zpool import -a\u001b[K\r\r\n+ zpool scrub -w tank\u001b[K\r\r\n+ zpool status -v\u001b[K\r\r\n pool: tank\u001b[K\r\r\n state: ONLINE\u001b[K\r\r\n scan: scrub repaired 0B in 00:00:00 with 0 errors on Thu Jan 9 00:05:26 2025\u001b[K\r\r\nconfig:\u001b[K\r\r\n\u001b[K\u001b[14;8H\u001b[1K\u001b[CNAME STATE READ WRITE CKSUM\u001b[K\u001b[15;8H\u001b[1K\u001b[Ctank ONLINE 0 0 0\u001b[K\u001b[16;8H\u001b[1K\u001b[C raidz1-0 ONLINE 0 0 0\u001b[K\u001b[17;8H\u001b[1K\u001b[C quizm0 ONLINE 0 0 0\u001b[K\u001b[18;8H\u001b[1K\u001b[C quizm1 ONLINE 0 0 0\u001b[K\u001b[19;8H\u001b[1K\u001b[C quizm2 ONLINE 0 0 0\u001b[K\u001b[20;8H\u001b[1K\u001b[C quizm3 ONLINE 0 0 0\u001b[K\r\r\n\u001b[K\r\r\nerrors: No known data errors\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n[quiz run finished. Ctrl-C or detach session to exit]\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg- 1:run* \"quiz\" 00:05 09-Jan-25\u001b[m\u000f"] 478 | [111.264253, "o", "\u001b[27;1H\u001b[?25h\u001b[?0c"] 479 | [112.532588, "o", "\u001b[?25l\u001b[?1c\u001b[H\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg 1:run- 2:bash* \"quiz\" 00:05 09-Jan-25\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[1;1H"] 480 | [112.552365, "o", "root@quiz:/# \u001b[?2004h"] 481 | [113.943558, "o", "#"] 482 | [114.079484, "o", " "] 483 | [114.149033, "o", "g"] 484 | [114.303863, "o", "r"] 485 | [114.426085, "o", "a"] 486 | [114.54253, "o", "b"] 487 | [114.703228, "o", " "] 488 | [114.795856, "o", "a"] 489 | [115.071983, "o", " "] 490 | [115.217821, "o", "n"] 491 | [115.278985, "o", "e"] 492 | [115.391975, "o", "w"] 493 | [115.463977, "o", " "] 494 | [115.589653, "o", "s"] 495 | [115.630662, "o", "h"] 496 | [115.783135, "o", "e"] 497 | [115.831847, "o", "l"] 498 | [116.008267, "o", "l"] 499 | [116.123699, "o", " "] 500 | [116.572097, "o", "a"] 501 | [116.653477, "o", "n"] 502 | [116.764258, "o", "d"] 503 | [116.806154, "o", " "] 504 | [116.899632, "o", "p"] 505 | [117.079427, "o", "o"] 506 | [117.276441, "o", "k"] 507 | [117.379326, "o", "e"] 508 | [117.490446, "o", " "] 509 | [117.580389, "o", "a"] 510 | [117.660512, "o", "r"] 511 | [117.691669, "o", "o"] 512 | [117.759572, "o", "u"] 513 | [117.929581, "o", "n"] 514 | [117.985344, "o", "d"] 515 | [118.089085, "o", ","] 516 | [118.177296, "o", " "] 517 | [118.282294, "o", "i"] 518 | [118.369577, "o", "f"] 519 | [118.43098, "o", " "] 520 | [118.619534, "o", "y"] 521 | [118.668502, "o", "o"] 522 | [118.754195, "o", "u"] 523 | [118.880136, "o", " "] 524 | [118.98887, "o", "l"] 525 | [119.194813, "o", "n"] 526 | [119.288006, "o", "e"] 527 | [119.443739, "o", "e"] 528 | [119.616114, "o", "d"] 529 | [119.915437, "o", "\b \b"] 530 | [120.135839, "o", "\b \b"] 531 | [120.321959, "o", "\b \b"] 532 | [120.508999, "o", "\b \b"] 533 | [120.674731, "o", "\b \b"] 534 | [120.835054, "o", "n"] 535 | [120.882032, "o", "e"] 536 | [121.040092, "o", "e"] 537 | [121.193142, "o", "d"] 538 | [121.284142, "o", " "] 539 | [121.394653, "o", "t"] 540 | [121.428195, "o", "o"] 541 | [121.941242, "o", "!"] 542 | [122.625472, "o", "\r\r\nroot@quiz:/# "] 543 | [123.815767, "o", "\r\r\nlogout\r\r\n\u001b[?2004l"] 544 | [123.823278, "o", "\u001b[?25l\u001b[?1c\u001b[1;8H\u001b[1K\u001b[C quizm2 ONLINE 0 0 0\u001b[K\u001b[2;8H\u001b[1K\u001b[C quizm3 ONLINE 0 0 0\u001b[K\r\r\n\u001b[K\r\r\nerrors: No known data errors\u001b[K\r\r\n+ zpool export -a\u001b[K\r\r\n+ zpool import -a\u001b[K\r\r\n+ zpool scrub -w tank\u001b[K\r\r\n+ zpool status -v\u001b[K\r\r\n pool: tank\u001b[K\r\r\n state: ONLINE\u001b[K\r\r\n scan: scrub repaired 0B in 00:00:00 with 0 errors on Thu Jan 9 00:05:26 2025\u001b[K\r\r\nconfig:\u001b[K\r\r\n\u001b[K\u001b[14;8H\u001b[1K\u001b[CNAME STATE READ WRITE CKSUM\u001b[K\u001b[15;8H\u001b[1K\u001b[Ctank ONLINE 0 0 0\u001b[K\u001b[16;8H\u001b[1K\u001b[C raidz1-0 ONLINE 0 0 0\u001b[K\u001b[17;8H\u001b[1K\u001b[C quizm0 ONLINE 0 0 0\u001b[K\u001b[18;8H\u001b[1K\u001b[C quizm1 ONLINE 0 0 0\u001b[K\u001b[19;8H\u001b[1K\u001b[C quizm2 ONLINE 0 0 0\u001b[K\u001b[20;8H\u001b[1K\u001b[C quizm3 ONLINE 0 0 0\u001b[K\r\r\n\u001b[K\r\r\nerrors: No known data errors\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n[quiz run finished. Ctrl-C or detach session to exit]\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[37m\u001b[48;5;52m\r\r\n[🧩quiz] 0:dmesg- 1:run* \"quiz\" 00:05 09"] 545 | [123.82356, "o", "-Jan-25\u001b[m\u000f\u001b[?25h\u001b[?0c\u001b[27;1H"] 546 | [126.178414, "o", "^C"] 547 | [126.185261, "o", "\u001b[1;28r\u001b[m\u000f\u001b[H\u001b[J\u001b[?25h\u001b[?0c\u001b[?1000l\u001b[?1002l\u001b[?1003l"] 548 | [126.185321, "o", "\u001b[?1006l\u001b[?1005l\u001b[?7727l"] 549 | [126.185343, "o", "\u001b[?1004l"] 550 | [126.186039, "o", "[detached (from session 0)]\r\r\n"] 551 | [126.187233, "o", "[INFO tini (1)] Main child exited normally (with status '0')\r\r\n[ 57.535145] Kernel panic - no"] 552 | [126.187297, "o", "t syncing: Attempted to kill ini"] 553 | [126.187318, "o", "t! exitcode=0x00"] 554 | [126.187572, "o", "000000\r\r\n[ 57.535373] CPU: 3 PID: 1 Comm: tini Tainted: P O "] 555 | [126.187634, "o", " 6.1.102 #27\r\r\n"] 556 | [126.187856, "o", "[ 57.535595] Call Trace:\r\r\n[ 57.535688] \r\r\n[ 57.535754] "] 557 | [126.187907, "o", "dump_stack_lvl+0x33/0x46\r\r\n[ 57.535893] "] 558 | [126.188071, "o", "panic+0x106/0x29"] 559 | [126.188166, "o", "2\r\r\n[ 57.536006] "] 560 | [126.188195, "o", "do_exit.cold+0x15/0x15\r\r\n[ 57.536160] "] 561 | [126.188217, "o", "? handle_mm_faul"] 562 | [126.188406, "o", "t+0x11c/0x200\r\r\n[ 57.536274] ? preempt_count_"] 563 | [126.188544, "o", "add+0x4e/0xb0\r\r\n[ 57.536373] do_group_exit+0x2d/0x80\r\r\n[ 57.536488] "] 564 | [126.188595, "o", "__x64_sys_exit_g"] 565 | [126.18862, "o", "roup+0x14/0x20\r\r\n"] 566 | [126.188968, "o", "[ 57.536620] do_syscall_64+0x34/0x80\r\r\n[ 57.536762] entry_SYSCALL_64_after_hwframe+0x6e/0xd8\r\r\n[ 57.536939] R"] 567 | [126.189096, "o", "IP: 0033:0x7f06519ae3c9\r\r\n[ 57.537046] Code: 00 4c 8b 05"] 568 | [126.189182, "o", " 39 da 0f 00 be e7 00 00 00 ba 3c 00 00 00 eb 12"] 569 | [126.189265, "o", " 0f 1f 44 00 00 89 d0 0f 05 48 3d 00 f0 ff ff 77"] 570 | [126.189343, "o", " 1c f4 89 f0 0f 05 <48> 3d 00 f0"] 571 | [126.189422, "o", " ff ff 76 e7 f7 d8 64 41 89 00 eb df 0f 1f 80 00"] 572 | [126.189502, "o", " 00 00\r\r\n[ 57.537487] R"] 573 | [126.189581, "o", "SP: 002b:00007ffe027dad08 EFLAGS"] 574 | [126.189668, "o", ": 00000246 ORIG_"] 575 | [126.189751, "o", "RAX: 00000000000000e7\r\r\n[ 57.537691] RAX: ffffffffffff"] 576 | [126.189864, "o", "ffda RBX: 00007f0651aa89e0 RCX: 00007f06519ae3c9"] 577 | [126.189944, "o", "\r\r\n[ 57.537910] RDX: 000000000000"] 578 | [126.190022, "o", "003c RSI: 00000000000000e7 RDI: "] 579 | [126.190073, "o", "0000000000000000"] 580 | [126.190199, "o", "\r\r\n[ 57.538097] RBP: 0000000000000000 R08: ffffffffffffff80 R09: "] 581 | [126.190267, "o", "00007ffe027dac3f\r\r\n[ 57.538275] R"] 582 | [126.19033, "o", "10: 00007ffe027dabc0 R11: 000000"] 583 | [126.190397, "o", "0000000246 R12: 00007f0651aa89e0"] 584 | [126.190458, "o", "\r\r\n[ 57.538437] R13: 00007f0651aa"] 585 | [126.190525, "o", "e2e0 R14: 0000000000000001 R15: "] 586 | [126.190587, "o", "00007f0651aae2c8\r\r\n"] 587 | [126.190813, "o", "[ 57.538610] \r\r\n"] 588 | [126.26908, "o", "[quiz] 20250109-11:06:01 done\r\n"] 589 | [126.271427, "o", "\u001b]0;shell: ~/code/quiz\u0007"] 590 | [126.290207, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 591 | [127.250202, "o", "#"] 592 | [128.356126, "o", " "] 593 | [128.463036, "o", "a"] 594 | [128.564502, "o", "n"] 595 | [128.65219, "o", "d"] 596 | [128.741809, "o", " "] 597 | [128.848111, "o", "a"] 598 | [128.928609, "o", "l"] 599 | [129.109401, "o", "l"] 600 | [129.204449, "o", " "] 601 | [129.296051, "o", "d"] 602 | [129.382914, "o", "i"] 603 | [129.46997, "o", "s"] 604 | [129.606383, "o", "a"] 605 | [129.708437, "o", "p"] 606 | [129.873363, "o", "p"] 607 | [129.926064, "o", "e"] 608 | [130.08081, "o", "a"] 609 | [130.199757, "o", "r"] 610 | [130.330628, "o", "e"] 611 | [130.48925, "o", "d"] 612 | [130.586032, "o", " "] 613 | [130.688665, "o", "l"] 614 | [130.764147, "o", "i"] 615 | [130.939143, "o", "k"] 616 | [132.095476, "o", "e"] 617 | [132.200543, "o", " "] 618 | [132.37202, "o", "b"] 619 | [132.427037, "o", "e"] 620 | [132.513864, "o", "f"] 621 | [132.611792, "o", "o"] 622 | [132.697732, "o", "r"] 623 | [132.799471, "o", "e"] 624 | [133.421666, "o", "."] 625 | [133.539776, "o", " "] 626 | [133.616083, "o", "s"] 627 | [133.816232, "o", "u"] 628 | [133.982561, "o", "p"] 629 | [134.050282, "o", "e"] 630 | [134.130383, "o", "r"] 631 | [134.356189, "o", "!"] 632 | [135.598096, "o", "\r\n\u001b[?2004l\r"] 633 | [135.601215, "o", "\u001b]0;shell: ~/code/quiz\u0007"] 634 | [135.614016, "o", "\u001b[?2004h\r\n\u001b[1;36mquiz\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35mmain\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;32m$\u001b[0m "] 635 | [136.301685, "o", "\u001b[?2004l\r\r\nexit\r\n"] 636 | --------------------------------------------------------------------------------