On Tue, Aug 16, 2022 at 09:03:55PM +0000, Miod Vallat wrote:
> > 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).
Here's the improved version of a new regress test I initially wrote to
compare real disks with vnd and block devices with duids.
I ran into this issue when trying to test installboot(8) changes on
vnd(4) rather than real hardware first.
The new regress spins up a vnd disk, creates a label and accesses the
disk through both its disklabel and block device... former is broken.
This could easily be adapted or copied into initial installboot(8)
tests which I wanted to do anyway.
regress/sys/kern/disk seems specific and yet broad enough; putting it
under lib/libutil/ due to opendev(3) makes little sense since that's
just the common entry point to what is actually a kernel bug and this
is not really vnd specific either as we're dealing with a
race condition/design flaw.
Feedback? Objections? OK?
Index: regress/sys/kern/disk/Makefile
===================================================================
RCS file: regress/sys/kern/disk/Makefile
diff -N regress/sys/kern/disk/Makefile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ regress/sys/kern/disk/Makefile 18 Aug 2022 10:06:49 -0000
@@ -0,0 +1,56 @@
+# $OpenBSD: $
+
+# anything calling opendev(3) with "sd0a" or "fc2aa4672193310c.a", e.g.
+# disklabel(8), newfs(8) or newfs_msdos(8)
+OPENDEV ?= /sbin/disklabel
+# write default MBR
+FORMAT ?= /sbin/fdisk -iy
+# write standard disklabel to get a valid DUID
+NEWLABEL ?= /sbin/disklabel -Aw
+
+# whether to trace diskmap(4)'s DIOCMAP handling DUIDs/block devices
+DO_TRACE ?= No
+
+IMGFILE = disk.img
+DEVFILE = vnd.txt
+DUIDFILE = duid.txt
+PART = a
+
+
+REGRESS_SETUP_ONCE = format-disk
+
+create-new-disk: create-new-disk
+ dd if=/dev/zero of=${IMGFILE} bs=1m count=0 seek=32
+ ${SUDO} vnconfig -- ${IMGFILE} > ${DEVFILE}
+format-disk: create-new-disk
+ ${SUDO} ${FORMAT} -- "$$(<${DEVFILE})"
+ ${SUDO} ${NEWLABEL} -- "$$(<${DEVFILE})"
+
+
+REGRESS_TARGETS = opendev-use-block \
+ opendev-use-duid
+
+opendev-use-block:
+ ${SUDO} ${OPENDEV} -- "$$(<${DEVFILE})${PART}"
+
+opendev-use-duid:
+ ${SUDO} disklabel -- "$$(<${DEVFILE})" | \
+ awk '$$1 == "duid:" { print $$2 }' > ${DUIDFILE}
+.if ${DO_TRACE:L} == "yes"
+ @# always run kdump regardless of newfs exit code
+ sh -uc '${SUDO} ktrace -- ${OPENDEV} -- "$$(<${DUIDFILE}).${PART}" ;\
+ ret=$$? ;\
+ ${SUDO} kdump -tcn | grep -FwA2 DIOCMAP ;\
+ exit $$ret'
+.else
+ ${SUDO} ${OPENDEV} -- "$$(<${DUIDFILE}).${PART}"
+.endif
+
+
+CLEANFILES = ${IMGFILE} ${DEVFILE} ${DUIDFILE} ktrace.out
+REGRESS_CLEANUP = cleanup
+
+cleanup:
+ ${SUDO} vnconfig -vu -- "$$(<${DEVFILE})"
+
+.include <bsd.regress.mk>