Use flock to avoid races with systemd-udevd

The race causes loop device partitions to briefly disappear. LP: #2045586.
ubuntu-core-desktop-noble
dann frazier 11 months ago
parent 20a43b540d
commit 3a00ad5263

5
debian/changelog vendored

@ -1,9 +1,14 @@
livecd-rootfs (24.04.26) UNRELEASED; urgency=medium livecd-rootfs (24.04.26) UNRELEASED; urgency=medium
[ Steve Langasek ]
* Share live-build/ubuntu/hooks/020-ubuntu-live.chroot_early across * Share live-build/ubuntu/hooks/020-ubuntu-live.chroot_early across
all flavors using new-style layered squashfs, removing need for all flavors using new-style layered squashfs, removing need for
kernel commandline options in debian-cd. kernel commandline options in debian-cd.
[ dann frazier ]
* Use flock to avoid races with systemd-udevd that cause loop device
partitions to briefly disappear.
-- Steve Langasek <steve.langasek@ubuntu.com> Wed, 17 Jan 2024 15:52:02 -0800 -- Steve Langasek <steve.langasek@ubuntu.com> Wed, 17 Jan 2024 15:52:02 -0800
livecd-rootfs (24.04.25) noble; urgency=medium livecd-rootfs (24.04.25) noble; urgency=medium

@ -63,36 +63,29 @@ mount_image() {
backing_img="$1" backing_img="$1"
local rootpart="$2" local rootpart="$2"
# As explained in excruciating detail in LP: #2045586, "losetup loop_device=$(losetup --show -f -P -v ${backing_img})
# -P" (a.k.a. --partscan) appears to race with udev in a way that
# prevents the device nodes for the partitions from being
# created. So instead we run losetup without -P, wait for udev to
# settle, then run partprobe and then settle udev again (which is
# probably unnecessary but at this point a bit more superstition
# can't hurt)
loop_device=$(losetup --show -f -v ${backing_img})
if [ ! -b ${loop_device} ]; then if [ ! -b ${loop_device} ]; then
echo "unable to find loop device for ${backing_img}" echo "unable to find loop device for ${backing_img}"
exit 1 exit 1
fi fi
udevadm settle # As explained in excruciating detail in LP: #2045586, losetup
partprobe ${loop_device} # races with udev in a way that can cause partition device files
udevadm settle # to briefly vanish. systemd docs say we can hold udev off by using
# flocks: https://systemd.io/BLOCK_DEVICE_LOCKING/
# `udevadm lock` isn't yet usable in Ubuntu, so we'll use flock for now
# Find the rootfs location # Find the rootfs location
rootfs_dev_mapper="${loop_device}p${rootpart}" rootfs_dev_mapper="${loop_device}p${rootpart}"
if [ ! -b "${rootfs_dev_mapper}" ]; then if flock -x ${loop_device} [ ! -b "${rootfs_dev_mapper}" ]; then
echo "${rootfs_dev_mapper} is not a block device"; echo "${rootfs_dev_mapper} is not a block device";
ls -l ${loop_device}p*
exit 1 exit 1
fi fi
# Add some information to the debug logs # Add some information to the debug logs
echo "Mounted disk image ${backing_img} to ${rootfs_dev_mapper}" echo "Mounted disk image ${backing_img} to ${rootfs_dev_mapper}"
blkid ${rootfs_dev_mapper} \ flock -x ${loop_device} blkid ${rootfs_dev_mapper} \
|| echo "blkid failed; continuing" || echo "blkid failed; continuing"
return 0 return 0
@ -225,10 +218,14 @@ mount_disk_image() {
mount_partition "${rootfs_dev_mapper}" $mountpoint mount_partition "${rootfs_dev_mapper}" $mountpoint
local boot_dev="${loop_device}p16" local boot_dev="${loop_device}p16"
if [ -b ${boot_dev} -a -e $mountpoint/boot ]; then if flock -x ${loop_device} \
mount "${boot_dev}" $mountpoint/boot [ -b ${boot_dev} -a -e $mountpoint/boot ]; then
flock -x ${loop_device} mount "${boot_dev}" $mountpoint/boot
fi fi
# Having one partition mounted should avoid udev-triggered partition
# rescans on that device, so we no longer need to flock.
local uefi_dev="${loop_device}p15" local uefi_dev="${loop_device}p15"
if [ -b ${uefi_dev} -a -e $mountpoint/boot/efi ]; then if [ -b ${uefi_dev} -a -e $mountpoint/boot/efi ]; then
mount "${uefi_dev}" $mountpoint/boot/efi mount "${uefi_dev}" $mountpoint/boot/efi

Loading…
Cancel
Save