@@ -19,12 +19,29 @@ _cleanup()
{
cd /
rm -f $tmp.*
- # lvm may have umounted it on I/O error, but in case it does not
- # wait a bit for lvm to settle, sigh..
- sleep 2
- $UMOUNT_PROG $mnt >/dev/null 2>&1
- $LVM_PROG vgremove -f $vgname >>$seqres.full 2>&1
- $LVM_PROG pvremove -f $SCRATCH_DEV >>$seqres.full 2>&1
+
+ # Tear down the lvm vg and snapshot.
+ #
+ # NOTE: We do the unmount and {vg,pv}remove in a loop here because
+ # dmeventd could be configured to unmount the filesystem automatically
+ # after the IO errors. That is racy with the umount we're trying to do
+ # here because there's a window in which the directory tree has been
+ # removed from the mount namespaces (so the umount call here sees no
+ # mount and exits) but the filesystem hasn't yet released the block
+ # device, which causes the vgremove here to fail.
+ #
+ # We "solve" the race by repeating the umount/lvm teardown until the
+ # block device goes away, because we cannot exit this test without
+ # removing the lvm devices from the scratch device -- this will cause
+ # other tests to fail.
+ while test -e /dev/mapper/$vgname-$snapname || \
+ test -e /dev/mapper/$vgname-$lvname; do
+ $UMOUNT_PROG $mnt >> $seqres.full 2>&1
+ $LVM_PROG vgremove -f $vgname >>$seqres.full 2>&1
+ $LVM_PROG pvremove -f $SCRATCH_DEV >>$seqres.full 2>&1
+ test $? -eq 0 && break
+ sleep 2
+ done
}
# get standard environment, filters and checks