Apply proper udev locking

Several commands during repart, resize and other actions
require a proper lock to be set for udev such that other
events knows about the locked state of a device and do
not mess with it until the command for which the lock
persists has completed. This commit applies proper udev
locks to all commands that requires it. In addition
incorrect code that was expected to prevent such race
conditions got dropped from the implementation.
This is related to bsc#1242987
This commit is contained in:
Marcus Schäfer 2025-07-17 12:33:17 +02:00
parent e5fbbcc8ab
commit db0fcd0894
No known key found for this signature in database
GPG Key ID: A16C1128698C8CAC
6 changed files with 45 additions and 55 deletions

View File

@ -226,16 +226,6 @@ function check_repart_possible {
return 0
}
function mask_fsck_root_service {
info "disable systemd-fsck-root.service"
systemctl mask systemd-fsck-root.service
}
function unmask_fsck_root_service {
info "enabling systemd-fsck-root.service"
systemctl unmask systemd-fsck-root.service
}
#======================================
# Perform repart/resize operations
#--------------------------------------
@ -243,22 +233,6 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin
setup_debug
# when repartitioning disks, the used tools can trigger re-reads of
# the partition table, in turn triggering systemd-fsck-root.service
# repeatedly via udev events, which finally can cause booting to fail with
# * start request repeated too quickly for systemd-fsck-root.service
# * Failed to start File System Check on /dev/disk/by-uuid...
# * Dependency failed for /sysroot.
# To avoid this, disable the root fsck (is finished at this point anyway
# *and* the filesystem is brand new ;) by masking it.
# "systemctl disable" does not work here, because it is event driven
# More details: https://github.com/SUSE/kiwi/issues/1034
# make sure we unmask the fsck service
trap unmask_fsck_root_service EXIT
mask_fsck_root_service
# initialize for disk repartition
initialize

View File

@ -37,22 +37,23 @@ function resize_filesystem {
local mpoint=/fs-resize
local fstype
fstype=$(probe_filesystem "${device}")
lock="udevadm lock --device ${device}"
case ${fstype} in
ext2|ext3|ext4)
resize_fs="resize2fs -f -p ${device}"
resize_fs="${lock} resize2fs -f -p ${device}"
;;
btrfs)
resize_fs="mkdir -p ${mpoint} && mount ${device} ${mpoint} &&"
resize_fs="${resize_fs} btrfs filesystem resize max ${mpoint}"
resize_fs="${resize_fs} ${lock} btrfs filesystem resize max ${mpoint}"
resize_fs="${resize_fs};umount ${mpoint} && rmdir ${mpoint}"
;;
xfs)
resize_fs="mkdir -p ${mpoint} && mount ${device} ${mpoint} &&"
resize_fs="${resize_fs} xfs_growfs ${mpoint}"
resize_fs="${resize_fs} ${lock} xfs_growfs ${mpoint}"
resize_fs="${resize_fs};umount ${mpoint} && rmdir ${mpoint}"
;;
swap)
resize_fs="mkswap ${device} --label SWAP"
resize_fs="${lock} mkswap ${device} --label SWAP"
;;
*)
# don't know how to resize this filesystem
@ -76,6 +77,7 @@ function check_filesystem {
local check_fs_return_ok
local fstype
fstype=$(probe_filesystem "${device}")
lock="udevadm lock --device ${device}"
case ${fstype} in
ext2|ext3|ext4)
# The exit code by e2fsck is the sum of the following conditions:
@ -87,13 +89,13 @@ function check_filesystem {
# 16 - Usage or syntax error
# 32 - E2fsck canceled by user request
# 128 - Shared library error
check_fs="e2fsck -p -f ${device}"
check_fs="${lock} e2fsck -p -f ${device}"
check_fs_return_ok="test \$? -le 2"
;;
btrfs)
# btrfs check returns a zero exit status if it succeeds.
# Non zero is returned in case of failure.
check_fs="btrfsck ${device}"
check_fs="${lock} btrfsck ${device}"
check_fs_return_ok="test \$? -eq 0"
;;
xfs)

View File

@ -74,7 +74,7 @@ function reencrypt_luks {
setup_progress_fifo ${progress}
(
# reencrypt, this will overwrite all key slots
cryptsetup reencrypt \
udevadm lock --device "${device}" cryptsetup reencrypt \
--progress-frequency 1 \
--key-file "${passphrase_file}" \
--key-slot "${keyslot}" \
@ -102,7 +102,7 @@ function activate_luks {
# but this requires to manually call luksOpen since
# with systemd-cryptsetup we saw it still asking for
# a passphrase
cryptsetup \
udevadm lock --device "${device}" cryptsetup \
--key-file /dev/zero \
--keyfile-size 32 \
luksOpen "${device}" luks

View File

@ -61,7 +61,9 @@ function get_volume_path_for_volume {
}
function resize_pyhiscal_volumes {
pvresize "$(get_root_map)"
local device
device=$(get_root_map)
udevadm lock --device "${device}" pvresize "${device}"
}
function resize_lvm_volumes_and_filesystems {

View File

@ -19,12 +19,14 @@ function deactivate_mdraid {
function activate_mdraid {
declare kiwi_RaidDev=${kiwi_RaidDev}
mdadm --assemble --scan "${kiwi_RaidDev}"
udevadm lock --device "${kiwi_RaidDev}" \
mdadm --assemble --scan "${kiwi_RaidDev}"
wait_for_storage_device "${kiwi_RaidDev}"
set_root_map "${kiwi_RaidDev}"
}
function resize_mdraid {
declare kiwi_RaidDev=${kiwi_RaidDev}
mdadm --grow --size=max "${kiwi_RaidDev}"
udevadm lock --device "${kiwi_RaidDev}" \
mdadm --grow --size=max "${kiwi_RaidDev}"
}

View File

@ -23,9 +23,11 @@ function create_partitions {
;;
esac
if type partprobe &> /dev/null;then
partprobe "${disk_device}"
udevadm lock --device "${disk_device}" \
partprobe "${disk_device}"
else
partx -u "${disk_device}"
udevadm lock --device "${disk_device}" \
partx -u "${disk_device}"
fi
}
@ -59,21 +61,23 @@ function create_msdos_partitions {
start_sector_from[$partid]=$(
_get_msdos_partition_start_sector "${disk_device}" "${partid}"
)
sfdisk --force --delete "${disk_device}" "${partid}"
udevadm lock --device "${disk_device}" \
sfdisk --force --delete "${disk_device}" "${partid}"
;;
"n")
# create a partition...
partid=${cmd_list[$index + 2]}
part_size_end=${cmd_list[$index + 4]}
echo "${start_sector_from[$partid]},${part_size_end}" > /tmp/sfdisk.in
sfdisk --force -N "${partid}" "${disk_device}" < /tmp/sfdisk.in
udevadm lock --device "${disk_device}" \
sfdisk --force -N "${partid}" "${disk_device}" < /tmp/sfdisk.in
;;
"t")
# change a partition type...
part_type=${cmd_list[$index + 2]}
partid=${cmd_list[$index + 1]}
sfdisk --force --change-id "${disk_device}" "${partid}" \
"${part_type}"
udevadm lock --device "${disk_device}" \
sfdisk --force --change-id "${disk_device}" "${partid}" "${part_type}"
;;
esac
index=$((index + 1))
@ -108,7 +112,8 @@ function create_gpt_partitions {
"d")
# delete a partition...
partid=${cmd_list[$index + 1]}
sgdisk --delete "${partid}" "${disk_device}"
udevadm lock --device "${disk_device}" \
sgdisk --delete "${partid}" "${disk_device}"
;;
"n")
# create a partition...
@ -116,17 +121,17 @@ function create_gpt_partitions {
partid=${cmd_list[$index + 2]}
part_size_start=${cmd_list[$index + 3]}
part_size_end=${cmd_list[$index + 4]}
sgdisk --new "${partid}:${part_size_start}:${part_size_end}" \
"${disk_device}"
sgdisk --change-name "${partid}:${part_name}" \
"${disk_device}"
udevadm lock --device "${disk_device}" \
sgdisk --new "${partid}:${part_size_start}:${part_size_end}" "${disk_device}"
udevadm lock --device "${disk_device}" \
sgdisk --change-name "${partid}:${part_name}" "${disk_device}"
;;
"t")
# change a partition type...
part_type=${cmd_list[$index + 2]}
partid=${cmd_list[$index + 1]}
sgdisk --typecode "${partid}:$(_to_guid "${part_type}")" \
"${disk_device}"
udevadm lock --device "${disk_device}" \
sgdisk --typecode "${partid}:$(_to_guid "${part_type}")" "${disk_device}"
;;
esac
index=$((index + 1))
@ -148,7 +153,8 @@ function create_dasd_partitions {
# partition table updated to the actual disk geometry. This is
# to circumvent the fdasd limitation of not being capable to
# expand the partition table up to the disk size bsc#1209247
parted --script --machine "${disk_device}" resizepart 1
udevadm lock --device "${disk_device}" \
parted --script --machine "${disk_device}" resizepart 1
for cmd in ${partition_setup};do
if [ "${ignore_cmd}" = 1 ] && echo "${cmd}" | grep -qE '[dntwq]';then
@ -182,7 +188,8 @@ function create_dasd_partitions {
done
echo "w" >> ${partition_setup_file}
echo "q" >> ${partition_setup_file}
fdasd "${disk_device}" < ${partition_setup_file} 1>&2
udevadm lock --device "${disk_device}" \
fdasd "${disk_device}" < ${partition_setup_file} 1>&2
}
function get_partition_node_name {
@ -336,7 +343,7 @@ function get_partition_uuid {
}
function relocate_gpt_at_end_of_disk {
if ! sfdisk --relocate gpt-bak-std "$1";then
if ! udevadm lock --device "$1" sfdisk --relocate gpt-bak-std "$1";then
die "Failed to write backup GPT at end of disk"
fi
}
@ -378,7 +385,8 @@ function activate_boot_partition {
pt_table_type=$(get_partition_table_type "${disk_device}")
if [[ "$(uname -m)" =~ i.86|x86_64 ]];then
if [ "${pt_table_type}" = "dos" ];then
sfdisk --activate "${disk_device}" "${boot_partition_id}"
udevadm lock --device "${disk_device}" \
sfdisk --activate "${disk_device}" "${boot_partition_id}"
fi
fi
}
@ -393,7 +401,9 @@ function create_hybrid_gpt {
# see man sgdisk for details
partition_count=3
fi
if ! sgdisk -h "$(seq -s : 1 "${partition_count}")" "${disk_device}";then
if ! udevadm lock --device "${disk_device}" \
sgdisk -h "$(seq -s : 1 "${partition_count}")" "${disk_device}"
then
die "Failed to create hybrid GPT/MBR !"
fi
}