I was bothered by the fact that we only sometimes see the double partition rescan in dmesg. If udev always rescans the partitions of a full block devices, shouldn't we always see those messages twice?
It turns out that udev doesn't rescan partitions just because a new block device appears. When it gets a uevent for a full block device, it registers an inotify watch on the device file for any process closing a file that was open in write mode. Presumably that process could've changed the partitions so, when that inotify event fires, it requests a partition rescan.
In our case, losetup has opened /dev/loop0 in write mode. When it calls into the LOOP_CONFIGURE ioctl(), a uevent will fire for /dev/loop0. If udev processes that event and adds the inotify watch before losetup closes the device, then closing the device will trigger the inotify event and udev will rescan.
I don't see a way to order operations to prevent this race. And I don't think we can "settle" our way out of it, because its not a uevent we're racing with, its the inotify event. But it looks like systemd may already have a solution for that: https://systemd.io/BLOCK_DEVICE_LOCKING/
I think as long as we run all of our commands that access the partition device files under `udevadm lock -d <fulldevice>`, then systemd should not trigger a partition reread underneath us. Here's what I'm thinking:
Of course, udevadm lock didn't exist until after jammy. And all versions that do have it, including the one in v255 in noble-proposed, are broken and need this patch backport:
I was bothered by the fact that we only sometimes see the double partition rescan in dmesg. If udev always rescans the partitions of a full block devices, shouldn't we always see those messages twice?
It turns out that udev doesn't rescan partitions just because a new block device appears. When it gets a uevent for a full block device, it registers an inotify watch on the device file for any process closing a file that was open in write mode. Presumably that process could've changed the partitions so, when that inotify event fires, it requests a partition rescan.
In our case, losetup has opened /dev/loop0 in write mode. When it calls into the LOOP_CONFIGURE ioctl(), a uevent will fire for /dev/loop0. If udev processes that event and adds the inotify watch before losetup closes the device, then closing the device will trigger the inotify event and udev will rescan.
I don't see a way to order operations to prevent this race. And I don't think we can "settle" our way out of it, because its not a uevent we're racing with, its the inotify event. But it looks like systemd may already have a solution for that: /systemd. io/BLOCK_ DEVICE_ LOCKING/
https:/
I think as long as we run all of our commands that access the partition device files under `udevadm lock -d <fulldevice>`, then systemd should not trigger a partition reread underneath us. Here's what I'm thinking:
https:/ /code.launchpad .net/~dannf/ livecd- rootfs/ +git/livecd- rootfs/ +merge/ 459549
Of course, udevadm lock didn't exist until after jammy. And all versions that do have it, including the one in v255 in noble-proposed, are broken and need this patch backport:
https:/ /github. com/systemd/ systemd/ commit/ ba340e2a75a0a16 031fcb7efa05cfd 250e859f17