[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [PATCH 0/1] loop mount: propagate errors correctly
From:       Thomas De Schampheleire <patrickdepinguin () gmail ! com>
Date:       2020-12-09 9:19:09
Message-ID: 20201209091910.25989-1-patrickdepinguin () gmail ! com
[Download RAW message or body]

From: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>

Hello,

When loop devices are mounted in parallel, the mount can fail but busybox
ignores it silently (a message is printed but the return code is still 0).

At the bottom of this mail is a (manual) test case that can show the issue quite
easily in case /dev/loop-control is available. Next mail is a patch that will
fix the error handling so that the initial mount actually fails.

However, it feels to me as if the mount shouldn't fail: the scenario is that
/dev/loop-control gives a 'free' number which later turns out to be not free
anymore because another mount used it too. This is an error that mount itself
could resolve by retrying, possibly with a maximum amount of attempts.
But that is another problem than actually reporting the failure.

When /dev/loop-control is not used, the problem does not seem to show, even
though we have seen sporadic (but less frequent) failures with a similar
description using busybox 1.29.x (before /dev/loop-control was used).

Best regards,
Thomas


Philippe Belet (1):
  loop device: report mount failure in case of set_loop failure

 libbb/loop.c       | 2 +-
 util-linux/mount.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)


--- test case; just run the script in an environment where 'busybox' is in path,
--- or pass it as first argument ---


#!/bin/sh
#set -x

busybox=${1:-busybox}
echo "Using busybox: $busybox"

# mount in loop
cnt=0
#innercnt=1
innercnt=10
stop=0

# Cleanup old mounts
for i in $(seq "$innercnt"); do
	umount /tmp/mountpoint$i >/dev/null 2>&1
	rm -f /tmp/mount-failed$i
done

dd if=/dev/zero of=/tmp/test.ext2 bs=1M count=1
mkfs.ext2 -F /tmp/test.ext2

# create initial file
mkdir  -p /tmp/mountpoint
$busybox mount -t ext2 -o loop /tmp/test.ext2 /tmp/mountpoint
echo foobar > /tmp/mountpoint/file
$busybox umount /tmp/mountpoint


while true; do

	echo "Mounting"
	for i in $(seq "$innercnt"); do
		rm -f /tmp/mount-failed$i
		(
		mkdir -p /tmp/mountpoint$i
		if ! $busybox mount -t ext2 -o loop /tmp/test.ext2 /tmp/mountpoint$i; then
			echo "Error: mount failed (cnt=$cnt, i=$i)!"
			touch /tmp/mount-failed$i
			stop=1
			break
		fi
		) &
	done
	if [ "$stop" -eq 1 ]; then
		break
	fi

	sleep 2
	echo "Check if mount completed after 2 seconds"
	for i in $(seq "$innercnt"); do
		if ! $busybox mount | grep "/tmp/mountpoint$i" ; then
			echo "Mount of /tmp/mountpoint$i seems to have failed. Checking once again after timeout..."
			sleep 2
			if ! $busybox mount | grep "/tmp/mountpoint$i"; then
				echo "Mount of /tmp/mountpoint$i definitely failed."
				if [ ! -e /tmp/mount-failed$i ]; then
					echo "Error: Mount failure was NOT reported by mount for i=$i"
				else
					echo "Mount failure was correctly reported for i=$i."
				fi
				stop=1
			fi
		fi
	done
	if [ "$stop" -eq 1 ]; then
		break
	fi

	echo "Checking contents"
	for i in $(seq "$innercnt"); do
		contents=$(cat /tmp/mountpoint$i/file)
		if [ "$contents" != "foobar" ]; then
			echo "Error: expected file contents differ (cnt=$cnt, i=$i)"
			echo "actual contents: $contents"
			echo "expected contents: foobar"
			stop=1
			break
		fi
	done
	if [ "$stop" -eq 1 ]; then
		break
	fi

	echo "Unmounting"
	for i in $(seq "$innercnt"); do
		$busybox umount /tmp/mountpoint$i
	done
	if [ "$stop" -eq 1 ]; then
		break
	fi

	echo "Increase cnt"
	let 'cnt+=1'

done

---------------------------------------------
Example output for an unpatched busybox:

sudo ./test-mount.sh ./busybox                                         
Using busybox: ./busybox
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.000866337 s, 1.2 GB/s
mke2fs 1.45.5 (07-Jan-2020)
Discarding device blocks: done                            
Creating filesystem with 1024 1k blocks and 128 inodes

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

Mounting
mount: can't setup loop device
mount: can't setup loop device
mount: can't setup loop device
mount: can't setup loop device
Check if mount completed after 2 seconds
/dev/loop0 on /tmp/mountpoint1 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop1 on /tmp/mountpoint2 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop2 on /tmp/mountpoint3 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop3 on /tmp/mountpoint4 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
Mount of /tmp/mountpoint5 seems to have failed. Checking once again after timeout...
Mount of /tmp/mountpoint5 definitely failed.
Error: Mount failure was NOT reported by mount for i=5
/dev/loop4 on /tmp/mountpoint6 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop5 on /tmp/mountpoint7 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
Mount of /tmp/mountpoint8 seems to have failed. Checking once again after timeout...
Mount of /tmp/mountpoint8 definitely failed.
Error: Mount failure was NOT reported by mount for i=8
Mount of /tmp/mountpoint9 seems to have failed. Checking once again after timeout...
Mount of /tmp/mountpoint9 definitely failed.
Error: Mount failure was NOT reported by mount for i=9
Mount of /tmp/mountpoint10 seems to have failed. Checking once again after timeout...
Mount of /tmp/mountpoint10 definitely failed.
Error: Mount failure was NOT reported by mount for i=10


------------------------------------
Example output for patched busybox:

sudo ./test-mount.sh ./busybox                                         
Using busybox: ./busybox
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.000874034 s, 1.2 GB/s
mke2fs 1.45.5 (07-Jan-2020)
Discarding device blocks: done                            
Creating filesystem with 1024 1k blocks and 128 inodes

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

Mounting
mount: can't setup loop device
mount: can't setup loop device
Error: mount failed (cnt=0, i=10)!
Error: mount failed (cnt=0, i=9)!
Check if mount completed after 2 seconds
/dev/loop0 on /tmp/mountpoint1 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop2 on /tmp/mountpoint2 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop3 on /tmp/mountpoint3 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop1 on /tmp/mountpoint4 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop6 on /tmp/mountpoint5 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop4 on /tmp/mountpoint6 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop5 on /tmp/mountpoint7 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
/dev/loop7 on /tmp/mountpoint8 type ext2 (rw,relatime,errors=continue,user_xattr,acl)
Mount of /tmp/mountpoint9 seems to have failed. Checking once again after timeout...
Mount of /tmp/mountpoint9 definitely failed.
Mount failure was correctly reported for i=9.
Mount of /tmp/mountpoint10 seems to have failed. Checking once again after timeout...
Mount of /tmp/mountpoint10 definitely failed.
Mount failure was correctly reported for i=10.



-- 
2.26.2

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic