Skip to content

Instantly share code, notes, and snippets.

@nomuranec
Created January 24, 2020 08:04
Show Gist options
  • Save nomuranec/359a4495900f26a1befa4380634b130f to your computer and use it in GitHub Desktop.
Save nomuranec/359a4495900f26a1befa4380634b130f to your computer and use it in GitHub Desktop.
#!/bin/bash
set -eu
# Based on:
# https://gist.githubusercontent.com/bboozzoo/d4b142229b1915ef7cc0cf8593599ad9/raw/367f593d7ef61a3659951f42c699e86820a8db75/reproduce.sh
export LC_ALL=C
LOOPS=40
COUNT="${COUNT-20}"
PREFIX=/tmp/mounttest
systemd_mp() {
local id
id="$1"
systemd-escape -p "$PREFIX/mount/$id"
}
cleanup() {
echo "--- cleaning up"
# cleanup
systemctl daemon-reload
for i in $(seq $COUNT); do
systemctl stop "$(systemd_mp "$i").mount" || true
rm -f "/etc/systemd/system/$(systemd_mp "$i").mount"
done
systemctl daemon-reload
for m in $(grep "$PREFIX/mount/" /proc/self/mountinfo | awk '{print $5}'); do
umount "$m"
done
losetup -D
}
random_sleep() {
local long
long="${1-5}"
sleep $(bc <<< "scale=4; $long*$RANDOM/32767")
}
if ! which bc 2>/dev/null; then
echo "error: bc not found, install proper package"
exit 1
fi
variant=0
case "${1-}" in
--cleanup)
cleanup
exit 0
;;
--variant-before)
variant=1
;;
--variant-systemd-mount)
variant=2
;;
--variant-mount)
variant=3
;;
--variant-many-reloads)
variant=4
;;
--variant-static-lodev)
variant=5
;;
esac
mkdir -p $PREFIX
# create a bunch of disks
for i in $(seq $COUNT); do
what="$PREFIX/disk-$i.img"
where="$PREFIX/mount/$i"
if [ ! -e "$what" ];then
dd if=/dev/zero of="$PREFIX/disk-$i.img" bs=1M count=10 >/dev/null
mkfs.ext4 -F "$PREFIX/disk-$i.img" >/dev/null
echo "$i" > "$PREFIX/canary"
debugfs -w -R "write $PREFIX/canary canary" "$PREFIX/disk-$i.img"
fi
mkdir -p "$PREFIX/mount/$i"
systemd_unit="$PREFIX/$(systemd_mp "$i").mount"
if [[ "$variant" = "5" ]]; then
losetup -f $what
lodev=$(losetup -l -O NAME -n -j "$what")
if [[ "$lodev" ]]; then
what=$lodev
else
echo "Failed to find loop dev for $what"
cleanup
exit 1
fi
fi
cat <<EOF > "$systemd_unit"
[Unit]
Description=mount unit for test $i
[Mount]
What=$what
Where=$where
Type=ext4
Options=nodev
EOF
done
trap "echo interrupted: run with --cleanup" SIGINT
if [[ "$variant" = "1" ]]; then
for i in $(seq $COUNT); do
unit_name="$(systemd_mp "$i").mount"
cp "$PREFIX/$unit_name" "/etc/systemd/system/$unit_name"
done
systemctl daemon-reload
fi
verify() {
local i
i="$1"
text="$(findmnt -ln)"
if ! echo "$text" | grep -q "$PREFIX/mount/$i "; then
date
echo "disk-$i missing"
echo "unit: tmp-mounttest-mount-$i.mount"
echo "mountinfo: $text"
sleep 10
return 1
fi
local content
content="$(cat "$PREFIX/mount/$i/canary")"
if [[ "$content" != "$i" ]]; then
echo "unexpected content in disk $i: '$content'"
return 1
fi
}
variant_0() {
local i
i="$1"
unit_name="$(systemd_mp "$i").mount"
cp "$PREFIX/$unit_name" "/etc/systemd/system/$unit_name"
random_sleep
systemctl daemon-reload
systemctl start "$unit_name"
random_sleep
verify "$i"
systemctl stop "$unit_name"
rm -f "/etc/systemd/system/$unit_name"
systemctl daemon-reload
}
variant_1() {
local i
i="$1"
unit_name="$(systemd_mp "$i").mount"
systemctl start "$unit_name"
random_sleep
verify "$i"
systemctl stop "$unit_name"
}
variant_2() {
local i
i="$1"
what="$PREFIX/disk-$i.img"
where="$PREFIX/mount/$i"
systemd-mount -o nodev "$what" "$where"
random_sleep
verify "$i"
systemd-mount --umount "$what" "$where"
}
variant_3() {
local i
i="$1"
what="$PREFIX/disk-$i.img"
where="$PREFIX/mount/$i"
mount -o nodev "$what" "$where"
#random_sleep 1
sleep 1
verify "$i"
umount "$where"
}
variant_4() {
local i
i="$1"
unit_name="$(systemd_mp "$i").mount"
if [[ "$i" == 1 ]]; then
cp "$PREFIX/$unit_name" "/etc/systemd/system/$unit_name"
fi
random_sleep
systemctl daemon-reload
if [[ "$i" == 1 ]]; then
systemctl start "$unit_name"
random_sleep
verify "$i"
systemctl stop "$unit_name"
rm -f "/etc/systemd/system/$unit_name"
fi
}
# variant_5 is same as variant_0
some_failed=0
[[ "$variant" == "5" ]] && losetup -l
for r in $(seq $LOOPS); do
echo "--- run $r $(date)"
[[ "$variant" == "3" ]] && losetup -l
for idx in $(seq $COUNT); do
(
set -eu
case "$variant" in
0)
variant_0 "$idx"
;;
1)
variant_1 "$idx"
;;
2)
variant_2 "$idx"
;;
3)
variant_3 "$idx"
;;
4)
variant_4 "$idx"
;;
5)
variant_0 "$idx"
;;
esac
) &
done
for _ in $(seq $COUNT); do
if ! wait -n ; then
some_failed=1
fi
done
if [[ "$some_failed" != "0" ]]; then
break
fi
if [[ "$variant" == "3" ]]; then
losetup -D || true
losetup -l
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment