During device probing GParted always explicitly calls ped_device_sync()
to flush the caches for coherency between the whole disk device and the
partition devices [1]. As the GParted_Core::flush_device() comment
explains, since v3.1.61-gfb99ba5 [2], libparted flushes the devices
every time a device is opened [3], so also explicitly doing this in
GParted is unnecessary. Therefore stop explicitly flushing the devices
in GParted, except when using libparted 3.1 and older which doesn't do
it itself.
The ped_device_open() and ped_device_close() needed for the
ped_device_sync() is also a trigger of device changes and udev rule
execution performing LVM Volume Group activation, because libparted
opens the device read-write [4]. This is another reason to remove it
when possible. However even when eliminated it does not solve the issue
of LVM VG activation because other triggers remain. Do want this change
first though so that the sequence of libparted calls isn't changed
immediately after documenting them and fixing the issue and so that
there is no doubt that this change doesn't fix the issue.
Removing this extra device flush saves a little bit of time, depending
on the speed of the drive and number of partitions. Sample savings on
my desktop:
Drive type and partitions Saving (seconds)
----------------------------- ----------------
fast SSD with 3 partitions 0.05
slow SSD with 12 partitions 0.27
HDD with 1 partition 0.05
VHDD in VM with 1 partition 0.14
VHDD in VM with 10 partitions 0.58
Also the settle_device() call in flush_device() needs to be kept to wait
for device changes and udev rule execution whether it is GParted
explicitly flushing the device or just libparted automatically doing it
for cache coherency in ped_device_get(). This is because:
1. Libparted <= 3.2 opens the whole disk device read-write for
ped_device_get() [5]. (This was changed with parted
v3.2.26-g44d5ae0 [6] to open the whole disk device read-only).
2. Libparted up to and including the latest 3.6 release still opens all
partition devices read-write for ped_device_get() [7].
3. A whole disk device FAT32 file system looks enough like a partition
table that both the Linux kernel and libparted think it is
partitioned:
# mkfs.fat -F32 /dev/sdb
mkfs.fat 4.2 (2021-01-31)
# grep sdb /proc/partitions
8 16 8388608 sdb
8 17 8388607 sdb1
# parted /dev/sdb print
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 8590MB
Sector size (logical/physical): 512B/512B
Partition Table: loop
Disk Flags:
Number Start End Size File system Flags
1 0s 16777215s 16777216s fat32
So the ped_device_get() call on a whole disk device FAT32 file system
still triggers device change and udev rule execution which needs to be
waited for, as this is exactly the case fixed previously by commit:
1382e0b828
Wait for udev change on /dev/DISK when querying whole device FS (!46)
[1] 3bea067596
Flush devices when scanning to prevent reading stale signatures (#723842)
[2] Revert "linux-commit: do not unnecessarily open partition device nodes"
http://git.savannah.gnu.org/cgit/parted.git/commit/?id=fb99ba5ebd0dc34204fc9f1014131d5d494805bc
[3] parted libparted/arch/linux.c:_device_open()
https://git.savannah.gnu.org/cgit/parted.git/tree/libparted/arch/linux.c?h=v3.6#n1752
1709 static int
1710 linux_open (PedDevice* dev)
1711 {
1712 return _device_open (dev, RW_MODE);
1713 }
1714
1715 static int
1716 _device_open (PedDevice* dev, int flags)
...
1752 _flush_cache (dev);
[4] parted libparted/device.c:ped_device_open() v3.6
https://git.savannah.gnu.org/cgit/parted.git/tree/libparted/device.c?h=v3.6#n226
parted libparted/arch/linux.c v3.6
https://git.savannah.gnu.org/cgit/parted.git/tree/libparted/arch/linux.c?h=v3.6
ped_device_open(...)
ped_architecture->dev_ops->open(...) = linux_open(...)
_device_open(..., RW_MODE)
open(..., O_RDWR)
[5] parted libparted/device.c:ped_device_get() v3.2
https://git.savannah.gnu.org/cgit/parted.git/tree/libparted/device.c?h=v3.2#n149
parted libparted/arch/linux.c v3.2
https://git.savannah.gnu.org/cgit/parted.git/tree/libparted/arch/linux.c?h=v3.2
ped_device_get(...)
ped_architecture->dev_ops->_new(...) = linux_new()
init_ide(...)
init_scsi(...)
init_generic(...)
ped_device_open(...)
ped_architecture->dev_ops->open(...) = linux_open(...)
open(..., O_RDWR)
[6] libparted: Use read only when probing devices on linux (#1245144)
http://git.savannah.gnu.org/cgit/parted.git/commit/?id=44d5ae0115c4ecfe3158748309e9912c5aede92d
[7] parted libparted/arch/linux.v v3.6
http://git.savannah.gnu.org/cgit/parted.git/tree/libparted/arch/linux.c?h=v3.6#n1660
1660 static void
1661 _flush_cache (PedDevice* dev)
...
1673 for (i = 1; i < lpn; i++) {
...
1680 if (!_partition_is_mounted_by_path(name)) {
1681 fd = open (name, WR_MODE, 0);
Closes#259 - Trying to deactivate LVM PV fails