Skip to content

Commit

Permalink
Workaround for loop device bug
Browse files Browse the repository at this point in the history
Creating a loop device sometimes fails due to a mismatch between kernel and user
code: (https://lore.kernel.org/lkml/8bed44f2-273c-856e-0018-69f127ea4258@linux.ibm.com/)
Work around this by ignoring losetup errors if the loop device was created, and retrying
failed mounts.
  • Loading branch information
marcone committed Apr 4, 2024
1 parent eb06f60 commit d34b3f5
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 7 deletions.
2 changes: 1 addition & 1 deletion run/archiveloop
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function timestamp () {
function fix_errors_in_image () {
local image="$1"
log "Running fsck on $image..."
loopback=$(losetup --show -f -P "$image")
loopback=$(losetup_find_show -P "$image")
# Use -p repair arg. It works with vfat and exfat.
/sbin/fsck "${loopback}p1" -- -p |& timestamp '| ' >> "$LOG_FILE" || echo ""
losetup -d "$loopback"
Expand Down
2 changes: 1 addition & 1 deletion run/make_snapshot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ function snapshot {
# /dev/loop0p1

# Use -p repair arg. It works with vfat and exfat.
LOOP=$(losetup --show -P -f "$newsnapname")
LOOP=$(losetup_find_show -P "$newsnapname")
PARTLOOP=${LOOP}p1

if [ "$1" = "fsck" ]
Expand Down
2 changes: 1 addition & 1 deletion setup/pi/create-backingfiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function add_drive () {
local partition_offset
partition_offset=$(first_partition_offset "$filename")

loopdev=$(losetup -o "$partition_offset" -f --show "$filename")
loopdev=$(losetup_find_show -o "$partition_offset" "$filename")
log_progress "Creating filesystem with label '$label'"
if [ "$useexfat" = true ]
then
Expand Down
28 changes: 28 additions & 0 deletions setup/pi/envsetup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,31 @@ else
export PICONFIG_PATH=/dev/null
fi

# losetup sometimes fails because of a mismatch between kernel and user land
# (https://lore.kernel.org/lkml/8bed44f2-273c-856e-0018-69f127ea4258@linux.ibm.com/)
# but even when it fails like that, testing shows the loop device gets created anyway
function losetup_find_show {
local lastarg="${@:$#}"
local loop=$(losetup -n -O NAME -j "$lastarg")
if losetup -f --show "$@"
then
return
fi
if [ -n "$loop" ]
then
# losetup failed, and there was already a previous loop device for the
# given file.
# Rather than trying to determine if a new loop device was created, just return
# an error.
return 1
fi
local newloop=$(losetup -n -O NAME -j "$lastarg")
if [ -z "$newloop" ]
then
# losetup truly failed and didn't even create a loop device
return 1
fi
echo "$newloop"
}

export -f losetup_find_show
21 changes: 17 additions & 4 deletions setup/pi/setup-teslausb
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,19 @@ function update_backingfiles_fstab_entry () {
fi
}

function mount_with_retry () {
for i in {1..5}
do
if mount "$@"
then
return
fi
setup_progress "'mount $*' failed, retrying"
sleep 1
done
return 1
}

function create_usb_drive_backing_files () {
if [ ! -e "$BACKINGFILES_MOUNTPOINT" ]
then
Expand Down Expand Up @@ -323,7 +336,7 @@ function create_usb_drive_backing_files () {
umount /mnt/cam > /dev/null || true
local ret=0
/root/bin/disable_gadget.sh || ret=$?
if (( (ret == 0) || (ret == 2) )) && mount /mnt/cam
if (( (ret == 0) || (ret == 2) )) && mount_with_retry /mnt/cam
then
mkdir -p /mnt/cam/TeslaCam
mkdir -p /mnt/cam/TeslaTrackMode
Expand All @@ -345,20 +358,20 @@ function create_usb_drive_backing_files () {

umount /mnt/cam

if mount /mnt/music
if [ -e /backingfiles/music_disk.bin ] && mount_with_retry /mnt/music
then
touch /mnt/music/.metadata_never_index
umount /mnt/music
fi

if mount /mnt/lightshow
if [ -e /backingfiles/lightshow_disk.bin ] && mount_with_retry /mnt/lightshow
then
mkdir -p /mnt/lightshow/LightShow
touch /mnt/lightshow/.metadata_never_index
umount /mnt/lightshow
fi

if mount /mnt/boombox
if [ -e /backingfiles/boombox_disk.bin ] && mount_with_retry /mnt/boombox
then
mkdir -p /mnt/boombox/Boombox
touch /mnt/boombox/.metadata_never_index
Expand Down
31 changes: 31 additions & 0 deletions tests/losetuptest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

# Repro case for the issue described here: https://lore.kernel.org/lkml/8bed44f2-273c-856e-0018-69f127ea4258@linux.ibm.com/
# When running this script on an affected kernel/userspace combo,
# such as Raspberry Pi OS with kernel 5.10.103 and losetup 2.33.1,
# you should see an occasional message about losetup having failed.

TESTIMG=/backingfiles/losetuptest.bin
while true
do
echo -n "$(date) looping: "
dd if=/dev/zero of=$TESTIMG bs=1M count=128 status=none
if losetup --sector-size=4096 -fP $TESTIMG
then
LOOP=$(losetup -n -O NAME -j /backingfiles/losetuptest.bin)
echo "$LOOP"
losetup -d $LOOP
else
echo losetup failed:
LOOP=$(losetup -n -O NAME -j /backingfiles/losetuptest.bin)
if [ -z "$LOOP" ]
then
echo "No loop device exists"
else
echo "loop device exists: $LOOP"
losetup -d $LOOP
fi
losetup -l
fi
rm $TESTIMG
done

0 comments on commit d34b3f5

Please sign in to comment.