diff -Nru cryptsetup-2.0.2/debian/changelog cryptsetup-2.0.2/debian/changelog --- cryptsetup-2.0.2/debian/changelog 2018-08-23 14:36:42.000000000 +0000 +++ cryptsetup-2.0.2/debian/changelog 2020-08-03 21:28:48.000000000 +0000 @@ -1,3 +1,26 @@ +cryptsetup (2:2.0.2-1ubuntu1.2) bionic; urgency=medium + + * Introduce retry logic for external invocations after mdadm (LP: #1879980) + - Currently, if an encrypted rootfs is configured on top of a MD RAID1 + array and such array gets degraded (e.g., a member is removed/failed) + the cryptsetup scripts cannot mount the rootfs, and the boot fails. + We fix that issue here by allowing the cryptroot script to be re-run + by initramfs-tools/local-block stage, as mdadm can activate degraded + arrays at that stage. + There is an initramfs-tools counter-part for this fix, but alone the + cryptsetup portion is harmless. + - d/i/cryptroot-script: set files used by cryptsetup/initramfs-tools + (flag that local-block is running and external invocation counter); + change logic from just wait 180 seconds / activating LVM every 10 + seconds to waiting 5 seconds first, then allowing initramfs-tools + to run mdadm (to activate degraded arrays) and call back at least + 30 times/seconds more / activating LVM every 1 second. + - d/i/cryptroot-script-block: set flag that local-block is running. + - d/i/cryptroot-script-bottom: clean up the flag and counter files. + - d/rules: ship the new local-bottom script. + + -- Guilherme G. Piccoli Mon, 03 Aug 2020 18:28:48 -0300 + cryptsetup (2:2.0.2-1ubuntu1.1) bionic-proposed; urgency=medium * SRU diff -Nru cryptsetup-2.0.2/debian/initramfs/cryptroot-script cryptsetup-2.0.2/debian/initramfs/cryptroot-script --- cryptsetup-2.0.2/debian/initramfs/cryptroot-script 2018-03-18 01:01:09.000000000 +0000 +++ cryptsetup-2.0.2/debian/initramfs/cryptroot-script 2020-08-03 21:28:48.000000000 +0000 @@ -187,13 +187,32 @@ setup_mapping() { - local opts count cryptopen cryptremove NEWROOT + local opts count cryptopen cryptremove NEWROOT initrd_cnt opts="$1" + CRYPTR_LOCAL_BLOCK="/run/cryptroot.local-block" + CRYPTR_CNT_FILE="/run/cryptroot.initrd.cnt" + if [ -z "$opts" ]; then return 0 fi + # We control here the number of re-invocations of this script from + # local-block - the heuristic is $ROOTDELAY/3, with a minimum of 30. + # This number is somewhat dictated by mdadm, we want to run more times + # than that script, to allow decrypting volumes on top of arrays. + + if [ -f "${CRYPTR_CNT_FILE}" ]; then + initrd_cnt=$(cat ${CRYPTR_CNT_FILE}) + else + initrd_cnt=${ROOTDELAY:-90} + initrd_cnt=$((initrd_cnt/3)) + if [ "${initrd_cnt}" -lt 30 ]; then + initrd_cnt=30 + fi + echo ${initrd_cnt} > "${CRYPTR_CNT_FILE}" + fi + parse_options "$opts" || return 1 if [ -z "$cryptkeyscript" ]; then @@ -237,28 +256,31 @@ # If the encrypted source device hasn't shown up yet, give it a # little while to deal with removable devices + # + # We also need to take into account RAID or other devices that may + # only be available on local-block stage. So, wait 5 seconds upfront, + # in local-top; if that fails, end execution relying on local-block + # invocations. Allow $ROOTDELAY/3 invocations with 1s sleep times (with + # a minimum of 30 invocations), and if after that we still fail, then it's + # really time to give-up. Variable $initrd_cnt tracks the re-invocations. + # + # Part of the lines below has been taken from initramfs-tools + # scripts/local's local_device_setup(), as suggested per + # https://launchpad.net/bugs/164044 . - # the following lines below have been taken from - # /usr/share/initramfs-tools/scripts/local, as suggested per - # https://launchpad.net/bugs/164044 if [ ! -e "$cryptsource" ]; then log_begin_msg "Waiting for encrypted source device..." - # Default delay is 180s - if [ -z "${ROOTDELAY}" ]; then - slumber=180 - else - slumber=${ROOTDELAY} + local slumber=1 + if [ ! -f "${CRYPTR_LOCAL_BLOCK}" ]; then + # we are running on local-top + slumber=5 fi - slumber=$(( ${slumber} * 10 )) while [ ! -e "$cryptsource" ]; do - # retry for LVM devices every 10 seconds - if [ ${slumber} -eq $(( ${slumber}/100*100 )) ]; then - activate_vg - fi + activate_vg + /bin/sleep 1 - /bin/sleep 0.1 slumber=$(( ${slumber} - 1 )) [ ${slumber} -gt 0 ] || break done @@ -273,11 +295,17 @@ # We've given up, but we'll let the user fix matters if they can if [ ! -e "${cryptsource}" ]; then - - echo " ALERT! ${cryptsource} does not exist." - echo " Check cryptopts=source= bootarg: cat /proc/cmdline" - echo " or missing modules, devices: cat /proc/modules; ls /dev" - panic -r "Dropping to a shell. Will skip ${cryptsource} if you can't fix." + if [ ${initrd_cnt} -le 0 ]; then + echo " ALERT! ${cryptsource} does not exist." + echo " Check cryptopts=source= bootarg: cat /proc/cmdline" + echo " or missing modules, devices: cat /proc/modules; ls /dev" + panic -r "Dropping to a shell. Will skip ${cryptsource} if you can't fix." + else + initrd_cnt=$((initrd_cnt - 1)) + echo ${initrd_cnt} > "${CRYPTR_CNT_FILE}" + return 0 # allow some attempts on local-block stage + fi + fi if [ ! -e "${cryptsource}" ]; then @@ -383,6 +411,11 @@ if [ "$cryptrootdev" = "yes" ] && [ $crypttries -gt 0 ] && [ $count -ge $crypttries ]; then message "cryptsetup ($crypttarget): maximum number of tries exceeded" + + if [ -f "${CRYPTR_CNT_FILE}" ]; then + echo 0 > "${CRYPTR_CNT_FILE}" + fi + message "cryptsetup: going to sleep for $failsleep seconds..." sleep $failsleep exit 1 diff -Nru cryptsetup-2.0.2/debian/initramfs/cryptroot-script-block cryptsetup-2.0.2/debian/initramfs/cryptroot-script-block --- cryptsetup-2.0.2/debian/initramfs/cryptroot-script-block 2018-03-18 01:01:09.000000000 +0000 +++ cryptsetup-2.0.2/debian/initramfs/cryptroot-script-block 2020-08-03 21:28:48.000000000 +0000 @@ -16,5 +16,6 @@ esac if [ -x /scripts/local-top/cryptroot ]; then + touch "/run/cryptroot.local-block" exec /scripts/local-top/cryptroot fi diff -Nru cryptsetup-2.0.2/debian/initramfs/cryptroot-script-bottom cryptsetup-2.0.2/debian/initramfs/cryptroot-script-bottom --- cryptsetup-2.0.2/debian/initramfs/cryptroot-script-bottom 1970-01-01 00:00:00.000000000 +0000 +++ cryptsetup-2.0.2/debian/initramfs/cryptroot-script-bottom 2020-08-03 21:28:48.000000000 +0000 @@ -0,0 +1,20 @@ +#!/bin/sh +set +x +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +# If we reached this stage, we do have a rootfs mounted +# so let's clean-up cryptroot setup mess... +rm -f "/run/cryptroot.local-block" +rm -f "/run/cryptroot.initrd.cnt" diff -Nru cryptsetup-2.0.2/debian/rules cryptsetup-2.0.2/debian/rules --- cryptsetup-2.0.2/debian/rules 2018-04-06 17:23:53.000000000 +0000 +++ cryptsetup-2.0.2/debian/rules 2020-08-03 21:28:48.000000000 +0000 @@ -156,6 +156,8 @@ $(CURDIR)/debian/cryptsetup/usr/share/initramfs-tools/scripts/local-top/cryptroot install -m 0755 debian/initramfs/cryptroot-script-block \ $(CURDIR)/debian/cryptsetup/usr/share/initramfs-tools/scripts/local-block/cryptroot + install -m 0755 debian/initramfs/cryptroot-script-bottom \ + $(CURDIR)/debian/cryptsetup/usr/share/initramfs-tools/scripts/local-bottom/cryptroot install -m 0644 debian/cryptdisks.bash_completion \ $(CURDIR)/debian/cryptsetup/usr/share/bash-completion/completions/cryptdisks install -m 0755 debian/cryptsetup.bug-script \