diff --git a/rear-add-lazy-unmounting-with-retry-RHEL-146134.patch b/rear-add-lazy-unmounting-with-retry-RHEL-146134.patch new file mode 100644 index 0000000..1233fdc --- /dev/null +++ b/rear-add-lazy-unmounting-with-retry-RHEL-146134.patch @@ -0,0 +1,167 @@ +From aadf9b40a48f4bbdc9f1ac22165bb2ecfed92207 Mon Sep 17 00:00:00 2001 +From: Johannes Meixner +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 + diff --git a/rear.spec b/rear.spec index 531e462..7d469f4 100644 --- a/rear.spec +++ b/rear.spec @@ -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 # ######################