> after a prompt from stsp@ and florian@, reporting that newfs_msdos
> fails when given an $duid.i argument, I set down to see what could be
> going on. My test using an USB stick failed to reprdouce the problem.
> Then I started using a vnd, and that shows the issue (once in a
> while). The feeling is that any disk devcied created on the fly might
> show this issue.

Moments ago kn@ stumbled upon this as well.

It turns out that, at least in the vnd case, there is indeed a race
between the scheduling of the task running disk_attach_callback and the
first access to the vnd device, which will cause the label to get read.

While vnd(4) has logic to read a label on-demand, disk_attach_callback
assumes it runs at a point where the label can safely be obtained, and
will not retry (because it sets DKF_OPENED, which never gets unset).

The following shell script will demonstrate the issue:

cat << EOF > test.sh
#! /bin/sh
set -e

dd if=/dev/zero of=img.bin bs=1m count=4 >/dev/null
iter=1
while [ $iter -lt 1000 ]; do
        vnconfig vnd0 img.bin
        fdisk -iy vnd0 > /dev/null
        disklabel -Aw vnd0 > /dev/null
        duid=$(sysctl hw.disknames|sed 's,.*vnd0:,,')
        disklabel $duid > /dev/null
        vnconfig -u vnd0
        iter=$((iter + 1))
done
EOF

(don't forget to vnconfig -u vnd0 if it fails).

The following diff makes vnd attempt to read a label as soon as the
VNDIOCSET ioctl is issued. However it will not fix softraid if it has a
similar problem, so a rework of the disk_attach operation might be a
better idea.

Index: vnd.c
===================================================================
RCS file: /OpenBSD/src/sys/dev/vnd.c,v
retrieving revision 1.177
diff -u -p -r1.177 vnd.c
--- vnd.c       23 Dec 2021 10:09:16 -0000      1.177
+++ vnd.c       16 Aug 2022 21:02:23 -0000
@@ -536,6 +536,9 @@ fail:
                sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
                disk_attach(&sc->sc_dev, &sc->sc_dk);
 
+               sc->sc_flags |= VNF_HAVELABEL;
+               vndgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0);
+
                disk_unlock(&sc->sc_dk);
 
                break;

Reply via email to