Fix unsuccessful unmout of rescue ESP that might result in a corrupted rescue USB

Resolves: RHEL-243227
This commit is contained in:
Lukáš Zaoral 2026-08-18 11:56:49 +02:00
parent 96c1ec4d69
commit cdfdbff5be
No known key found for this signature in database
GPG Key ID: 39157506DD67752D
2 changed files with 171 additions and 0 deletions

View File

@ -0,0 +1,167 @@
From aadf9b40a48f4bbdc9f1ac22165bb2ecfed92207 Mon Sep 17 00:00:00 2001
From: Johannes Meixner <jsmeix@suse.com>
Date: Tue, 4 Mar 2025 13:10:18 +0100
Subject: [PATCH] New umount_mountpoint_retry_lazy function (#3408)
In lib/global-functions.sh added
new umount_mountpoint_retry_lazy function
which is basically a copy of the code in
output/ISO/Linux-i386/700_create_efibootimg.sh
which had been added there via
https://github.com/rear/rear/pull/2909
Call the umount_mountpoint_retry_lazy function
in output/ISO/Linux-i386/700_create_efibootimg.sh
and also in output/USB/Linux-i386/100_create_efiboot.sh
see https://github.com/rear/rear/issues/3397
---
usr/share/rear/lib/global-functions.sh | 56 +++++++++++++++++++
.../ISO/Linux-i386/700_create_efibootimg.sh | 46 ++-------------
.../USB/Linux-i386/100_create_efiboot.sh | 11 +++-
3 files changed, 70 insertions(+), 43 deletions(-)
diff --git a/usr/share/rear/lib/global-functions.sh b/usr/share/rear/lib/global-functions.sh
index 95c96e510d..ada71ca49d 100644
--- a/usr/share/rear/lib/global-functions.sh
+++ b/usr/share/rear/lib/global-functions.sh
@@ -863,6 +863,62 @@ function umount_mountpoint_lazy() {
umount $v -f -l "$mountpoint" >&2
}
+# Unmount mountpoint $1 first with sleep and retry then with lazy
+# cf. https://github.com/rear/rear/pull/2909
+# $2 is optional string to show the user what is mounted (fallback value for $2 is $1)
+# for example when $1 is a meaningless directory like /var/tmp/rear.XXXXXXXXXXXXXXX/tmp/somedir
+# then $2 should be a meaningful string to help the user to understand what it actually is
+# cf. https://github.com/rear/rear/wiki/Coding-Style#make-yourself-understood
+function umount_mountpoint_retry_lazy() {
+ local mountpoint="$1"
+ contains_visible_char "$mountpoint" || BugError "umount_mountpoint_retry_lazy() called with empty mountpoint argument '$mountpoint'"
+ test -d "$mountpoint" -o -b "$mountpoint" || Error "umount_mountpoint_retry_lazy mountpoint '$mountpoint' neither directory nor block device"
+ local what_is_mounted="$2"
+ contains_visible_char "$what_is_mounted" || what_is_mounted="$mountpoint"
+ # First attempt to umount:
+ umount $v "$mountpoint" && return 0
+ # First attempt to umount failed:
+ Log "Failed to umount $what_is_mounted (will retry after one second)"
+ # Normal umounting something directly after some I/O command (like 'cp' above)
+ # may sometimes fail with "target is busy" (cf. 'busy' and 'lazy' in "man umount")
+ # so we retry after one second to increase likelihood that it then succeeds
+ # cf. https://github.com/rear/rear/issues/2908#issuecomment-1382000811 ("sleep 1 works fine")
+ # and https://github.com/rear/rear/issues/3397#issuecomment-2656911018 (sleep also worked here)
+ # because normal umount is preferred over more sophisticated attempts
+ # like lazy umount or enforced umount which raise their own specific troubles
+ # and the -M option for fuser which is used below is not available on older
+ # Linux distributions like RHEL6 and SLES11 so 'sleep 1' and retry is best:
+ sleep 1
+ # Retry the same umount as in the first attempt:
+ umount $v "$mountpoint" && return 0
+ # Retry to umount also failed:
+ Log "Again failed to umount $what_is_mounted"
+ # Show in the log file what still uses the mountpoint:
+ Log "$what_is_mounted is still in use by ('kernel mount' is always there)"
+ # The -M option avoids that fuser may show all processes using the '/' filesystem
+ # e.g. for mountpoint $TMP_DIR/somedir ($TMP_DIR = $BUILD_DIR/tmp = /var/tmp/rear.XXXXXXXXXXXXXXX/tmp/)
+ # when $TMP_DIR/somedir got umounted just before fuser starts, see "man fuser":
+ # The mount -m option will match any file within the same device as the specified file,
+ # use the -M option as well if you mean to specify only the mount point.
+ # So when $TMP_DIR/somedir is umounted 'fuser -v -M -m $TMP_DIR/somedir' only shows
+ # "Specified filename /var/tmp/rear.XXXXXXXXXXXXXXX/tmp/somedir is not a mountpoint"
+ # instead of all processes using '/' (or /var/ or /var/tmp/ if one is a mountpoint)
+ # which would be misleading information that may even look scaring and cause false alarm.
+ # Older systems do not support -M but we must use it to avoid misleading information or false alarm.
+ # Since this code path is exceptional and the output is used only for information and only in the log file
+ # we do not care when fuser fails with "M: unknown signal; fuser -l lists signals":
+ fuser -v -M -m "$mountpoint" 1>&2 || Log "Presumably 'fuser' does not support the -M option"
+ DebugPrint "Trying 'umount --lazy $mountpoint' (normal umount failed)"
+ # Do only plain 'umount --lazy' without additional '--force'
+ # because enforced umount raises its own specific troubles
+ # so we cannot use the umount_mountpoint_lazy() function here:
+ umount $v --lazy "$mountpoint" && return 0
+ # Lazy umount also failed:
+ Log "Also failed to umount --lazy $what_is_mounted"
+ # It is the task of the caller what to do (e.g. Error or LogPrintError or ignore with only a Log message):
+ return 1
+}
+
# Change $1 to user input or leave default value on empty input
function change_default
{
diff --git a/usr/share/rear/output/ISO/Linux-i386/700_create_efibootimg.sh b/usr/share/rear/output/ISO/Linux-i386/700_create_efibootimg.sh
index b889df1bb7..f18f0e2add 100644
--- a/usr/share/rear/output/ISO/Linux-i386/700_create_efibootimg.sh
+++ b/usr/share/rear/output/ISO/Linux-i386/700_create_efibootimg.sh
@@ -45,46 +45,12 @@ mount $v -o loop -t vfat $TMP_DIR/efiboot.img $TMP_DIR/efi_virt || Error "Failed
cp $v -r $TMP_DIR/mnt/. $TMP_DIR/efi_virt
# Umounting the EFI virtual image:
-local what_is_mounted="EFI virtual image $TMP_DIR/efiboot.img at $TMP_DIR/efi_virt"
-if ! umount $v $TMP_DIR/efiboot.img ; then
- # Normal umounting something directly after some I/O command (like 'cp' above)
- # may sometimes fail with "target is busy" (cf. 'busy' and 'lazy' in "man umount")
- # so we retry after one second to increase likelihood that it then succeeds
- # cf. https://github.com/rear/rear/issues/2908#issuecomment-1382000811 ("sleep 1 works fine")
- # because normal umount is preferred over more sophisticated attempts
- # like lazy umount or enforced umount which raise their own specific troubles
- # and the -M option for fuser which is used below is not available on older
- # Linux distributions like RHEL6 and SLES11 so 'sleep 1' and retry is best:
- Log "Failed to umount $what_is_mounted (will retry after one second)"
- sleep 1
- if ! umount $v $TMP_DIR/efiboot.img ; then
- Log "Again failed to umount $what_is_mounted"
- Log "$what_is_mounted is still in use by ('kernel mount' is always there)"
- # The -M option avoids that fuser may show all processes using the '/' filesystem
- # ( $TMP_DIR is $BUILD_DIR/tmp which is /var/tmp/rear.XXXXXXXXXXXXXXX/tmp/ )
- # when $TMP_DIR/efiboot.img got umounted just before fuser starts, see "man fuser":
- # The mount -m option will match any file within the same device as the specified file,
- # use the -M option as well if you mean to specify only the mount point.
- # So when $TMP_DIR/efiboot.img is umounted 'fuser -v -M -m $TMP_DIR/efi_virt' only shows
- # "Specified filename /var/tmp/rear.XXXXXXXXXXXXXXX/tmp/efi_virt is not a mountpoint"
- # instead of all processes using '/' (or /var/ or /var/tmp/ if one is a mountpoint)
- # which would be misleading information that may even look scaring and cause false alarm.
- # Older systems do not support -M but we must use it to avoid misleading information or false alarm.
- # Since this code path is exceptional and the output is used only for information purposes,
- # we do not care when fuser fails with "M: unknown signal; fuser -l lists signals":
- fuser -v -M -m $TMP_DIR/efi_virt 1>&2 || Log "Presumably 'fuser' does not support the -M option"
- DebugPrint "Trying 'umount --lazy $TMP_DIR/efiboot.img' (normal umount failed)"
- # Do only plain 'umount --lazy' without additional '--force'
- # so we do not use the umount_mountpoint_lazy() function here:
- if ! umount $v --lazy $TMP_DIR/efiboot.img ; then
- # When umounting the EFI virtual image fails it is no hard error so only inform the user
- # so he can understand why later cleanup_build_area_and_end_program() may show
- # "Could not remove build area" (when lazy umount could not clean up things until then)
- # cf. https://github.com/rear/rear/issues/2908
- LogPrintError "Could not umount $what_is_mounted"
- fi
- fi
-fi
+local what_is_mounted="EFI virtual image $TMP_DIR/efiboot.img on $TMP_DIR/efi_virt"
+# When umounting the EFI virtual image fails it is no hard error so only inform the user
+# so he can understand why later cleanup_build_area_and_end_program() may show
+# "Could not remove build area" (when lazy umount could not clean up things until then)
+# cf. https://github.com/rear/rear/issues/2908
+umount_mountpoint_retry_lazy "$TMP_DIR/efi_virt" "$what_is_mounted" || LogPrintError "Could not umount $what_is_mounted"
# Move efiboot.img into ISO directory:
mv $v -f $TMP_DIR/efiboot.img $TMP_DIR/isofs/boot/efiboot.img || Error "Failed to move efiboot.img to isofs/boot/efiboot.img"
diff --git a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
index 9e5242093c..ac58f11926 100644
--- a/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
+++ b/usr/share/rear/output/USB/Linux-i386/100_create_efiboot.sh
@@ -153,8 +153,13 @@ EOF
fi
# Cleanup of EFI temporary mount point:
-if umount $efi_mpt ; then
- rmdir $efi_mpt || LogPrintError "Could not remove temporary directory '$efi_mpt' (you should do it manually)"
+local what_is_mounted="EFI partition '$efi_part' on '$efi_mpt'"
+# When umounting the EFI partition fails it is no hard error so only inform the user
+# so he can understand why later cleanup_build_area_and_end_program() may show
+# "Could not remove build area" (when lazy umount could not clean up things until then)
+# cf. https://github.com/rear/rear/issues/3397
+if umount_mountpoint_retry_lazy "$efi_mpt" "$what_is_mounted" ; then
+ rmdir "$efi_mpt" || LogPrintError "Could not remove temporary directory '$efi_mpt' (you should do it manually)"
else
- LogPrintError "Could not umount EFI partition '$efi_part' at '$efi_mpt' (you should do it manually)"
+ LogPrintError "Could not umount $what_is_mounted' (you should do it manually)"
fi

View File

@ -94,6 +94,10 @@ Patch139: rear-fix-lftp-options-pass-RHEL-178087.patch
# https://github.com/rear/rear/commit/e95afd1c8580454451fb791991b30839be3141b7
Patch140: rear-add-squashfs-overlay-split-support-RHEL-192030.patch
# fix unsuccessful unmout of rescue ESP that might result in a corrupted rescue USB
# https://github.com/rear/rear/commit/aadf9b40a48f4bbdc9f1ac22165bb2ecfed92207
Patch141: rear-add-lazy-unmounting-with-retry-RHEL-146134.patch
######################
# downstream patches #
######################