. "$BST_LIB" # BST-TIMEOUT: 240 # 55 cases, ~45 execs, no loops and no corpus. MEASURED at # elapsed=46s on hz1 (2026-08-25, # ==BST-SUITE aoetools elapsed=46s cases=55==) and declared # at ~5x, the ratio 99-sg3-utils.test uses. Nothing here # waits on a network: # every transport call is refused at socket(2) and returns # immediately, and aoe-sancheck's per-interface thread exits # at its own ethopen() rather than reaching its poll loop. # aoetools -- an ATA-over-Ethernet userland on a machine that has no wire for it # and no disk. # # WHAT THIS MACHINE CAN AND CANNOT TEST. AoE is a block protocol carried # directly in Ethernet frames, so the twelve commands here need PF_PACKET raw # sockets to reach the wire and the block layer to present what they find. # arch/wasm32/configs/wasm32_defconfig carries "# CONFIG_PACKET is not set" # (annotated there as a deliberate v0.1 omission, beside NET_NS and IPV6, under # a CONFIG_NET=y/CONFIG_INET=y core). It also reads "# CONFIG_BLOCK is not set", # but the superproject's kernel rig merges distros/common/linux-6.12/config/ # common.fragment over it, which sets CONFIG_BLOCK=y (linux-in-the-browser # 8c34495): /sys/block and /proc/partitions exist and are empty, with no AoE # driver behind them. So no AoE target is reachable and none could be. # # WHAT IS THEREFORE ASSERTED FOR REAL. Everything the tools do BEFORE they touch # either subsystem, which on this package is most of their code: option parsing # for all five programs that parse options, the usage text each prints, the # version table aoe-version composes, and the exit status each documents. Those # are arithmetic on argv and strings, they have no I/O in them, and they are the # same on every architecture -- so a wasm32 build that got them wrong is a wasm32 # build that is wrong, with no environmental excuse available. # # WHAT IS PROBED RATHER THAN ASSUMED. The two gaps above are read at runtime # from ${LIBEXEC}/aoetools-tests/aoetools-probe and every branch below is # written against the live answer, so this suite stays correct the day the # kernel grows either one: the skips turn back into assertions on their own # evidence rather than on a comment. # # AND THE CONTROLS ARE THE POINT OF THE PROBE. "PF_PACKET was refused" is a # statement about the kernel only while this process can open other sockets. The # probe therefore opens AF_INET stream, AF_INET datagram and AF_UNIX stream in # the same run, and every skip below is gated on all three succeeding. If they # stop succeeding, this suite reds rather than quietly skipping -- which is the # failure mode a suite full of environmental skips is otherwise built to have. # # WHY NOT A NATIVE ORACLE. The comparison suites next door (sg3-utils, lvm2) # compare byte-for-byte against an x86-64 build of the same version, because # their subject is a decoder whose output is a pure function of its input. This # package's output is a function of the ENVIRONMENT -- which device nodes exist, # which interfaces are up, whether sysfs carries a block tree -- so an oracle # built on the build host would differ from a correct target run for reasons # that are not defects. The invariant text (usage, version, the documented # diagnostics) is asserted directly instead, and it was read off a native build # of aoetools-36 during the port rather than transcribed from the source. bst_ok aoetools/suite-canary # first line: absorbs brintos/linux#96, which drops it require aoeping aoetools/present # --- the twelve commands upstream's Makefile installs ------------------------- # # Checked by name, and not for tidiness. Upstream's install rule is # `for f in ${COMMANDS}; do install ... || break; done` -- it stops at the FIRST # missing file and still returns success, so one program that failed to link # removes itself and every command after it from the package in silence. # aoe-sancheck is last in that list and is also the only target built with a # leading `-` in the Makefile, so make ignores its failure too: two independent # ways for it to vanish without reddening a build. for t in aoe-discover aoe-interfaces aoe-mkshelf aoe-revalidate aoe-flush \ aoe-stat aoe-mkdevs aoe-version coraid-update \ aoeping aoecfg aoe-sancheck; do if command -v "$t" >/dev/null 2>&1; then bst_ok "aoetools/present/$t" else bst_notok "aoetools/present/$t" "not installed -- upstream's install loop stops at the first missing command and returns success" fi done # --- the probe --------------------------------------------------------------- P=/usr/libexec/aoetools-tests/aoetools-probe if [ ! -x "$P" ]; then bst_notok aoetools/probe/present "no probe at $P -- aoetools-tests is not installed, so nothing below can be attributed" exit 0 fi PO=$("$P" 2>&1); prc=$? if bst_execfail "$PO"; then bst_unrun aoetools/probe/runs "$PO" exit 0 fi case "$PO" in *"probe end"*) bst_ok aoetools/probe/runs ;; *) bst_notok aoetools/probe/runs "rc=$prc, no 'probe end' -- the probe did not finish, so its values below are partial: $(_bst_1line "$PO")" exit 0 ;; esac # field -- the value of on the probe's # line. Reads from a variable, never a redirect: a top-level stdin # redirect on the virtiofs root makes dup2(2) return 513 and ash exits, ending # the suite silently (brintos/linux#73). field() { printf '%s\n' "$PO" | sed -n "s/^$1 / /p" \ | sed -n "s/.*[ ]$2=\\([^ ]*\\).*/\\1/p" | sed -n 1p } # state -- the third word of a ` present|absent` line. state() { printf '%s\n' "$PO" | sed -n "s/^$1 [^ ]* \\([a-z]*\\)$/\\1/p" | sed -n 1p } pkt_rc=$(field packet-socket rc) pkt_name=$(field packet-socket name) pkt_err=$(printf '%s\n' "$PO" | sed -n 's/^packet-socket .*strerror=//p' | sed -n 1p) inet_s=$(field inet-stream rc) inet_d=$(field inet-dgram rc) unix_s=$(field unix-stream rc) sysblock=$(state sysfs-block) procpart=$(state proc-partitions) sysaoe=$(state sysfs-aoe) devdir=$(state devdir) if_all=$(field ifcensus all) if_eth=$(field ifcensus eth) thr_rc=$(field pthread rc) thr_name=$(field pthread name) thr_ran=$(field pthread ran) mknod_rc=$(field mknod-blk rc) mknod_name=$(field mknod-blk name) # Echo what the probe answered, one line at a time, prefixed so it is greppable # and plainly not a result line. Costs nothing and saves the next reader of a # stored run a boot: every branch below is a function of these values, and # without them a stored dump records the verdicts without the evidence. printf '%s\n' "$PO" | while read -r _dl; do [ -n "$_dl" ] && printf '#diag: aoetools probe: %s\n' "$_dl" done # --- the controls ------------------------------------------------------------ # # Three sockets this kernel DOES carry. They are asserted, not recorded: while # they pass, a PF_PACKET refusal is a fact about the packet family; if they ever # fail, it is a fact about the process and nothing below may be attributed to # CONFIG_PACKET. check_eq aoetools/control/inet-stream 0 "$inet_s" check_eq aoetools/control/inet-dgram 0 "$inet_d" check_eq aoetools/control/unix-stream 0 "$unix_s" controls_ok=no if [ "$inet_s" = 0 ] && [ "$inet_d" = 0 ] && [ "$unix_s" = 0 ]; then controls_ok=yes fi # --- the two measurements ---------------------------------------------------- # # Recorded as values with a definite answer required, rather than asserted in # one direction: both outcomes are legitimate results, and a suite that demands # the absence would red on the good day. packet=unknown case "$pkt_rc:$pkt_name" in 0:*) packet=present ;; -1:EAFNOSUPPORT) packet=absent ;; -1:*) packet=refused ;; esac case "$packet" in present) bst_ok aoetools/packet/answer ;; # the kernel grew CONFIG_PACKET absent) bst_ok aoetools/packet/answer ;; # socket(2) -> EAFNOSUPPORT, as configured refused) bst_notok aoetools/packet/answer "PF_PACKET refused with $pkt_name ($pkt_err), which is neither 'the family is absent' (EAFNOSUPPORT) nor success -- the tools' failures below cannot be attributed to CONFIG_PACKET on this evidence" ;; *) bst_notok aoetools/packet/answer "the probe printed no usable packet-socket line" ;; esac case "$sysblock" in present|absent) bst_ok aoetools/block/answer ;; *) bst_notok aoetools/block/answer "the probe printed no usable sysfs-block line" ;; esac # --- argument parsing, usage text and exit status ---------------------------- # # None of these reaches a socket or a device node, so all of them run on their # merits on any kernel. Exit statuses are upstream's own and are checked # exactly: aoeping is the only tool here that exits 0 on a usage request, and # aoecfg is the only one whose -h is an INVALID option that happens to print the # usage on its way out with status 1. Getting those two backwards is precisely # the sort of thing a "the tool ran" assertion cannot see. apr() { # apr _aid=$1; _awant=$2; _aneedle=$3; shift 3 _aout=$("$@" 2>&1); _arc=$? case "$_aout" in *"$_aneedle"*) _ahit=1 ;; *) _ahit=0 ;; esac if bst_execfail "$_aout"; then bst_unrun "$_aid" "$_aout" elif [ "$_arc" -eq "$_awant" ] && [ "$_ahit" -eq 1 ]; then bst_ok "$_aid" else bst_notok "$_aid" "rc=$_arc want=$_awant want:'$_aneedle' got:'$(_bst_1line "$_aout")'"; fi } # -h is aoeping's documented usage request and the one success exit in the package. apr aoetools/argv/aoeping-h 0 'usage: aoeping [options] {shelf} {slot} {netif}' aoeping -h apr aoetools/argv/aoeping-h-opts 0 '-S perform SMART command' aoeping -h # Fewer than the three required positionals -> usage, EXIT_FAILURE. apr aoetools/argv/aoeping-noargs 1 'usage: aoeping [options] {shelf} {slot} {netif}' aoeping apr aoetools/argv/aoeping-2args 1 'usage: aoeping [options] {shelf} {slot} {netif}' aoeping 1 2 # An unknown option: aoeping's OWN diagnostic, not getopt's. getopt prints a # second line naming argv[0], which is a path here and a basename on a native # build, so it is deliberately not what this asserts. apr aoetools/argv/aoeping-badopt 1 'aoeping Error: unrecognized option: Z' aoeping -Z # aoecfg's getopt string is "s:c:t:v" -- it has no -h at all, so -h takes the # default branch and usage() exits 1. Asserted in that direction on purpose. apr aoetools/argv/aoecfg-badopt 1 'usage: aoecfg [-c cmd] [-s cfgstr] [-t timeout] [shelf slot] [net]' aoecfg -h # -c takes one of read/test/prefix/set/fset; anything else is usage(), exit 1, # and it happens before any socket is opened. apr aoetools/argv/aoecfg-badcmd 1 'usage: aoecfg [-c cmd] [-s cfgstr] [-t timeout] [shelf slot] [net]' aoecfg -c no-such-command apr aoetools/argv/mkdevs-noargs 1 'Usage: aoe-mkdevs {dir}' aoe-mkdevs apr aoetools/argv/mkshelf-noargs 1 'Usage: aoe-mkshelf {dir} {shelfaddress}' aoe-mkshelf apr aoetools/argv/revalidate-noargs 1 'Usage: aoe-revalidate e{major}.{minor}' aoe-revalidate apr aoetools/argv/coraid-noargs 1 'usage: coraid-update {update file} {AoE device}' coraid-update # The interface-name validation is a /sys/class/net lookup and is reached before # any device node is touched, so it holds whatever the AoE state of the machine. apr aoetools/argv/interfaces-badif 1 'aoe-interfaces Error: "bst-no-such-if0" is not a network interface' aoe-interfaces bst-no-such-if0 apr aoetools/argv/interfaces-c-arg 1 'aoe-interfaces Error: -c flag takes no arguments' aoe-interfaces -c eth0 # --- aoe-version ------------------------------------------------------------- # # The one command in the package that is expected to succeed on this image, and # the closest thing it has to a --version. Its three fields come from three # different places and are checked separately: the packaged version is a literal # in the script, the installed-driver field is modinfo's answer, and the # running-driver field is read from /sys/module/aoe. vout=$(aoe-version 2>&1); vrc=$? if bst_execfail "$vout"; then bst_unrun aoetools/version/rc "$vout" else check_eq aoetools/version/rc 0 "$vrc" # "aoetools: 36" -- the version this recipe built, asserted against the # recipe's PV rather than against whatever the script happens to say. vpkg=$(printf '%s\n' "$vout" | sed -n 's/^ *aoetools:[ ]*//p') check_eq aoetools/version/aoetools-field 36 "$vpkg" vrun=$(printf '%s\n' "$vout" | sed -n 's/^ *running aoe driver:[ ]*//p') if [ "$sysaoe" = absent ]; then # No /sys/module/aoe -- there is no module and cannot be one, since the # kernel is built without CONFIG_MODULES. The script's own answer for # that case is the literal "(none)". check_eq aoetools/version/running-field '(none)' "$vrun" else bst_skip aoetools/version/running-field "/sys/module/aoe exists on this image, so the field reports a live driver version and there is no fixed value to assert" fi vins=$(printf '%s\n' "$vout" | sed -n 's/^ *installed aoe driver:[ ]*//p') # Asserted unconditionally, and not gated on whether modinfo is installed: # what decides this field is "# CONFIG_MODULES is not set", which means # there is no aoe module and cannot be one. modinfo IS on this image and # answers "Module aoe not found", so both of the script's probes come back # empty and it substitutes its own "(unknown)". Any other value here would # mean the image grew loadable modules, which is a finding rather than a # reason to skip. check_eq aoetools/version/installed-field '(unknown)' "$vins" fi # --- the AoE character devices ---------------------------------------------- # # Four commands do nothing but write to a node under /dev/etherd that the AoE # driver creates. With no driver the nodes are absent and each prints its own # diagnostic and exits 1 -- which is the documented behaviour, so it is asserted # rather than skipped. Gated on the probe's answer so an image that grows the # driver reds here and asks for these to be rewritten, instead of passing on a # stale expectation. if [ "$devdir" = absent ]; then apr aoetools/devdir/discover 1 'aoe-discover: /dev/etherd/discover does not exist or is not writeable.' aoe-discover apr aoetools/devdir/flush 1 'aoe-flush: /dev/etherd/flush does not exist or is not writeable.' aoe-flush # Which of aoe-interfaces' two refusals runs is decided by /sys/class/net, # not by the AoE driver, so both are asserted rather than one being skipped: # rejecting a name sysfs does not carry is equally correct behaviour. if [ -d /sys/class/net/lo ]; then apr aoetools/devdir/interfaces 1 'aoe-interfaces: /dev/etherd/interfaces does not exist or is not writeable.' aoe-interfaces lo else apr aoetools/devdir/interfaces 1 'aoe-interfaces Error: "lo" is not a network interface' aoe-interfaces lo fi # No argument at all is the list form: it reads the module's iflist from # sysfs, and with no module `false` sets the exit status. Empty output, rc 1. ilout=$(aoe-interfaces 2>&1); ilrc=$? if bst_execfail "$ilout"; then bst_unrun aoetools/devdir/interfaces-list "$ilout" elif [ "$ilrc" -eq 1 ] && [ -z "$ilout" ]; then bst_ok aoetools/devdir/interfaces-list else bst_notok aoetools/devdir/interfaces-list "rc=$ilrc want=1 with no output, got:'$(_bst_1line "$ilout")'"; fi else bst_skip aoetools/devdir/discover "/dev/etherd exists on this image, so these four commands reach a real node and their documented absent-node diagnostics are not what runs" bst_skip aoetools/devdir/flush "/dev/etherd exists on this image" bst_skip aoetools/devdir/interfaces "/dev/etherd exists on this image" bst_skip aoetools/devdir/interfaces-list "/dev/etherd exists on this image" fi # --- the transport ---------------------------------------------------------- # # aoeping and aoecfg both open their raw socket in the same dial() in linux.c, # so on a kernel without PF_PACKET they fail identically and at the same place: # perror("got bad socket"), then getea() on the -1 descriptor, then exit 1. # # This is asserted, not skipped. The refusal path is real code doing real work # and it is what a user of this image will meet, so it is worth pinning; and # because the message carries strerror(errno), it can be checked against the # probe's own reading of the same errno rather than against a hard-coded string. # What IS skipped -- and only on the probe's confirmed absence -- is the half # that needs a target on the wire, which no assertion here can reach. if [ "$packet" = absent ] && [ "$controls_ok" = yes ]; then apr aoetools/transport/aoeping-refusal 1 "got bad socket: $pkt_err" aoeping 1 2 lo apr aoetools/transport/aoecfg-refusal 1 "got bad socket: $pkt_err" aoecfg -c read 1 2 lo # The second half of dial()'s failure: getea() is handed the -1 and reports # it. Present because a build that returned a live fd from a failed socket(2) # would pass the case above and fail this one. apr aoetools/transport/aoeping-getea 1 "Can't get hw addr: Bad file descriptor" aoeping 1 2 lo bst_skip aoetools/transport/aoeping-target "socket(PF_PACKET, SOCK_RAW, ETH_P_AOE) returns EAFNOSUPPORT on this kernel (CONFIG_PACKET is not set) while AF_INET and AF_UNIX both open, so no AoE target is reachable and the config-query exchange cannot be exercised" bst_skip aoetools/transport/aoecfg-target "same PF_PACKET absence -- aoecfg's read/test/prefix/set/fset exchange needs a target to answer it" elif [ "$controls_ok" != yes ]; then bst_notok aoetools/transport/aoeping-refusal "the controls did not pass (inet-stream=$inet_s inet-dgram=$inet_d unix-stream=$unix_s), so this process cannot open ordinary sockets either and no aoetools failure may be attributed to CONFIG_PACKET" bst_notok aoetools/transport/aoecfg-refusal "same -- see aoetools/transport/aoeping-refusal" bst_notok aoetools/transport/aoeping-getea "same -- see aoetools/transport/aoeping-refusal" bst_notok aoetools/transport/aoeping-target "same -- see aoetools/transport/aoeping-refusal" bst_notok aoetools/transport/aoecfg-target "same -- see aoetools/transport/aoeping-refusal" else bst_skip aoetools/transport/aoeping-refusal "PF_PACKET opened on this image ($pkt_name), so the refusal path these cases pin is not the one that runs -- rewrite them against a live socket" bst_skip aoetools/transport/aoecfg-refusal "PF_PACKET opened on this image" bst_skip aoetools/transport/aoeping-getea "PF_PACKET opened on this image" bst_skip aoetools/transport/aoeping-target "PF_PACKET opened on this image, so this case is now reachable and needs an AoE target on the wire to assert against" bst_skip aoetools/transport/aoecfg-target "PF_PACKET opened on this image" fi # --- aoe-sancheck ------------------------------------------------------------ # # The one program here that completes successfully with no AoE anything: it # enumerates interfaces, spawns a thread per one named eth*, and prints two # summary tables however that goes. Its threads exit at their own ethopen(), so # it is bounded on this image and never reaches the poll loop that waitsecs # governs. scout=$(aoe-sancheck 2>&1); src=$? if bst_execfail "$scout"; then bst_unrun aoetools/sancheck/rc "$scout" else check_eq aoetools/sancheck/rc 0 "$src" case "$scout" in *'Probing...'*) bst_ok aoetools/sancheck/probing ;; *) bst_notok aoetools/sancheck/probing "want:'Probing...' got:'$(_bst_1line "$scout")'" ;; esac case "$scout" in *'INTERFACE SUMMARY'*) bst_ok aoetools/sancheck/if-summary ;; *) bst_notok aoetools/sancheck/if-summary "want:'INTERFACE SUMMARY' got:'$(_bst_1line "$scout")'" ;; esac case "$scout" in *'DEVICE SUMMARY'*) bst_ok aoetools/sancheck/dev-summary ;; *) bst_notok aoetools/sancheck/dev-summary "want:'DEVICE SUMMARY' got:'$(_bst_1line "$scout")'" ;; esac fi # Whether aoe-sancheck creates a thread at all is decided by its interface # census, not by the packet family: ethlist() keeps only names beginning "eth", # so on an image with none it spawns nothing and the pthread path is never # exercised. That is a fact about the image and is reported as one -- the probe # runs the thread itself so the capability is still measured either way. # Scored three ways on the live answer, so the tracked refusal is distinguished # from an untracked one rather than both landing as the same red: # threads work -> ok, and aoe-sancheck's threaded path is exercisable # EAGAIN -> the refusal hardwarejs#29 tracks, carried as a skip # anything else -> a failure nobody is tracking, and a real finding if [ "$thr_rc" = 0 ] && [ "$thr_ran" = 1 ]; then bst_ok aoetools/sancheck/pthread elif [ "$thr_name" = EAGAIN ]; then bst_skip aoetools/sancheck/pthread "pthread_create(3) returns EAGAIN: this runtime refuses a thread-mode clone outright, the coro substrate being single-lane per process -- brintos/hardwarejs#29. It costs aoetools nothing on this image, because ethlist() finds no eth* interface and aoe-sancheck therefore spawns no thread; the probe runs one itself so the capability is measured rather than assumed" else bst_notok aoetools/sancheck/pthread "the probe's pthread_create/join did not complete and not with the EAGAIN hardwarejs#29 tracks (rc=$thr_rc name=$thr_name ran=$thr_ran) -- aoe-sancheck spawns one thread per eth* interface and would lose them" fi if [ "${if_eth:-0}" -gt 0 ] 2>/dev/null; then # There IS an eth* interface, so jcheck() ran and hit ethopen()'s socket(2). case "$scout" in *'got bad socket'*) bst_ok aoetools/sancheck/eth-refusal ;; *) bst_notok aoetools/sancheck/eth-refusal "eth=$if_eth interface(s) present and PF_PACKET is $packet, so ethopen() should have reported a refusal; got:'$(_bst_1line "$scout")'" ;; esac else bst_skip aoetools/sancheck/eth-refusal "the interface census found $if_all interface(s) and none named eth*, so ethlist() returns 0 and aoe-sancheck spawns no thread -- there is no ethopen() call to observe" fi # --- the block half ---------------------------------------------------------- # # aoe-stat's first act is `test ! -d /sys/block`, so which of its two failures # runs is decided by CONFIG_BLOCK and by nothing else; this kernel has it, so the # empty-/sys/block branch is the one that runs. Both are exit 1 and only # the output distinguishes them, which is why the message is asserted and not # just the status. stout=$(aoe-stat 2>&1); strc=$? if bst_execfail "$stout"; then bst_unrun aoetools/block/aoe-stat "$stout" elif [ "$sysblock" = absent ]; then if [ "$strc" -eq 1 ] && [ "${stout#*sysfs is not mounted}" != "$stout" ]; then bst_ok aoetools/block/aoe-stat else bst_notok aoetools/block/aoe-stat "no /sys/block on this kernel, so aoe-stat should exit 1 saying sysfs is not mounted; rc=$strc got:'$(_bst_1line "$stout")'" fi else # /sys/block exists but holds no e. entry: the loop emits # nothing and the closing `grep .` sets the status. Empty output, rc 1. if [ "$strc" -eq 1 ] && [ -z "$stout" ]; then bst_ok aoetools/block/aoe-stat else bst_notok aoetools/block/aoe-stat "/sys/block exists with no AoE device, so aoe-stat should exit 1 with no output; rc=$strc got:'$(_bst_1line "$stout")'"; fi fi # coraid-update's first act after its argument check is to look its target up in # aoe-stat's output. Reached with two arguments, and it fails for the target # rather than for the arguments -- a different branch from the usage case above. apr aoetools/block/coraid-target 1 'coraid-update Error: "e0.0" is not an AoE target' coraid-update bst-update-file e0.0 # aoe-mkshelf builds the static device nodes a udev-less system would need. # Driven with n_partitions=1 into TMPDIR, so it makes 16 nodes rather than 256 # and touches nothing outside the test's own directory. Whether mknod(2) can # make a block node at all is the probe's answer, and the two branches are # different findings: a kernel with no block layer still lets a filesystem # CREATE the inode, so a refusal here is about the root filesystem rather than # about CONFIG_BLOCK. W=${TMPDIR:-/tmp}/bst-aoetools.$$ if ! mkdir -p "$W" 2>/dev/null; then bst_notok aoetools/block/mkshelf "cannot create working directory $W" elif [ "$mknod_rc" = 0 ]; then mkout=$(n_partitions=1 aoe-mkshelf "$W" 0 2>&1); mkrc=$? made=$(ls "$W" 2>/dev/null | wc -l | tr -d " ") if bst_execfail "$mkout"; then bst_unrun aoetools/block/mkshelf "$mkout" elif [ "$mkrc" -eq 0 ] && [ "$made" -eq 16 ]; then bst_ok aoetools/block/mkshelf else bst_notok aoetools/block/mkshelf "rc=$mkrc want=0 with 16 nodes, made=$made got:'$(_bst_1line "$mkout")'"; fi else mkout=$(n_partitions=1 aoe-mkshelf "$W" 0 2>&1); mkrc=$? if bst_execfail "$mkout"; then bst_unrun aoetools/block/mkshelf "$mkout" elif [ "$mkrc" -ne 0 ]; then bst_ok aoetools/block/mkshelf else bst_notok aoetools/block/mkshelf "mknod(2) of a block node was refused with $mknod_name for the probe, so aoe-mkshelf cannot have succeeded; rc=$mkrc got:'$(_bst_1line "$mkout")'"; fi fi rm -rf "$W" 2>/dev/null # aoe-mkdevs refuses outright when udev is running or when the driver is in # dynamic-device mode, and neither holds here -- so what it meets is the same # mknod question as aoe-mkshelf. Only its argument-check branch is asserted # above; this records the sysfs facts the two share so a reader of a future run # can tell which branch was taken without re-deriving it. case "$procpart" in present|absent) bst_ok aoetools/block/proc-partitions ;; *) bst_notok aoetools/block/proc-partitions "the probe printed no usable proc-partitions line" ;; esac