Small timing changes in the kernel loop device handling broke the
following loop:
while :; do mount -o loop,ro isofs.iso isofs/; umount isofs/; done
which quickly reports:
mount: /mnt: can't read superblock on /dev/loop0.
umount: /mnt: not mounted.
And this loop is broken because of a subtle interaction with
systemd-udevd that also opens the loop device. The race seems to be in
mount(8) handling itself and the altered kernel timing makes it happen.
It look like:
bash systemd-udevd
mount -o loop,ro isofs.iso isofs/
/dev/loop0 is created and bound to isofs.iso, autoclear is set for
loop0
opens /dev/loop0
umount isofs/
loop0 still lives because systemd-udev still has device open
mount -o loop,ro isofs.iso isofs/
gets to mnt_context_setup_loopdev()
loopcxt_find_overlap()
sees loop0 is still valid and with proper parameters
reuse = true;
close /dev/loop0
last fd closed => loop0 is
cleaned up
loopcxt_get_fd()
opens loop0 but it is no longer the device we wanted!
calls mount(2) which fails because we cannot read from the loop device
Fix the problem by rechecking that loop device is still attached after
opening the device. This makes sure the kernel will not autoclear the
device anymore.