2021-06-08 10:04:35 +03:00
#!/usr/bin/env bash
2021-10-17 19:13:06 +03:00
# SPDX-License-Identifier: LGPL-2.1-or-later
2021-06-08 10:04:35 +03:00
set -eux
set -o pipefail
2023-05-16 20:09:13 +03:00
# shellcheck source=test/units/util.sh
. " $( dirname " $0 " ) " /util.sh
2022-07-20 10:56:25 +03:00
teardown_test_dependencies( ) (
set +eux
if mountpoint /tmp/deptest; then
umount /tmp/deptest
fi
if [ [ -n " ${ LOOP } " ] ] ; then
losetup -d " ${ LOOP } " || :
fi
if [ [ -n " ${ LOOP_0 } " ] ] ; then
losetup -d " ${ LOOP_0 } " || :
fi
if [ [ -n " ${ LOOP_1 } " ] ] ; then
losetup -d " ${ LOOP_1 } " || :
fi
rm -f /tmp/testsuite-60-dependencies-0.img
rm -f /tmp/testsuite-60-dependencies-1.img
rm -f /run/systemd/system/tmp-deptest.mount
systemctl daemon-reload
return 0
)
setup_loop( ) {
truncate -s 30m " /tmp/testsuite-60-dependencies- ${ 1 ? } .img "
sfdisk --wipe= always " /tmp/testsuite-60-dependencies- ${ 1 ? } .img " <<EOF
label:gpt
name = " loop ${ 1 ? } -part1 "
EOF
LOOP = $( losetup -P --show -f " /tmp/testsuite-60-dependencies- ${ 1 ? } .img " )
2022-08-20 01:09:21 +03:00
udevadm wait --settle --timeout= 10 " ${ LOOP } "
udevadm lock --device= " ${ LOOP } " mkfs.ext4 -L " partname ${ 1 ? } -1 " " ${ LOOP } p1 "
2022-07-20 10:56:25 +03:00
}
check_dependencies( ) {
local escaped_0 escaped_1 after
escaped_0 = $( systemd-escape -p " ${ LOOP_0 } p1 " )
escaped_1 = $( systemd-escape -p " ${ LOOP_1 } p1 " )
if [ [ -f /run/systemd/system/tmp-deptest.mount ] ] ; then
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_not_in "local-fs-pre.target" " $after "
assert_in "remote-fs-pre.target" " $after "
assert_in "network.target" " $after "
fi
# mount LOOP_0
mount -t ext4 " ${ LOOP_0 } p1 " /tmp/deptest
sleep 1
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_in "local-fs-pre.target" " $after "
assert_not_in "remote-fs-pre.target" " $after "
assert_not_in "network.target" " $after "
assert_in " ${ escaped_0 } .device " " $after "
assert_in " blockdev@ ${ escaped_0 } .target " " $after "
assert_not_in " ${ escaped_1 } .device " " $after "
assert_not_in " blockdev@ ${ escaped_1 } .target " " $after "
umount /tmp/deptest
if [ [ -f /run/systemd/system/tmp-deptest.mount ] ] ; then
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_not_in "local-fs-pre.target" " $after "
assert_in "remote-fs-pre.target" " $after "
assert_in "network.target" " $after "
fi
# mount LOOP_1 (using fake _netdev option)
mount -t ext4 -o _netdev " ${ LOOP_1 } p1 " /tmp/deptest
sleep 1
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_not_in "local-fs-pre.target" " $after "
assert_in "remote-fs-pre.target" " $after "
assert_in "network.target" " $after "
assert_not_in " ${ escaped_0 } .device " " $after "
assert_not_in " blockdev@ ${ escaped_0 } .target " " $after "
assert_in " ${ escaped_1 } .device " " $after "
assert_in " blockdev@ ${ escaped_1 } .target " " $after "
umount /tmp/deptest
if [ [ -f /run/systemd/system/tmp-deptest.mount ] ] ; then
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_not_in "local-fs-pre.target" " $after "
assert_in "remote-fs-pre.target" " $after "
assert_in "network.target" " $after "
fi
# mount tmpfs
mount -t tmpfs tmpfs /tmp/deptest
sleep 1
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_in "local-fs-pre.target" " $after "
assert_not_in "remote-fs-pre.target" " $after "
assert_not_in "network.target" " $after "
assert_not_in " ${ escaped_0 } .device " " $after "
assert_not_in " blockdev@ ${ escaped_0 } .target " " $after "
assert_not_in " ${ escaped_1 } .device " " $after "
assert_not_in " blockdev@ ${ escaped_1 } .target " " $after "
umount /tmp/deptest
if [ [ -f /run/systemd/system/tmp-deptest.mount ] ] ; then
after = $( systemctl show --property= After --value tmp-deptest.mount)
assert_not_in "local-fs-pre.target" " $after "
assert_in "remote-fs-pre.target" " $after "
assert_in "network.target" " $after "
fi
}
test_dependencies( ) {
if systemd-detect-virt --quiet --container; then
echo "Skipping test_dependencies in container"
return
fi
trap teardown_test_dependencies RETURN
setup_loop 0
LOOP_0 = " ${ LOOP } "
LOOP =
setup_loop 1
LOOP_1 = " ${ LOOP } "
LOOP =
mkdir -p /tmp/deptest
# without .mount file
check_dependencies
# create .mount file
mkdir -p /run/systemd/system
cat >/run/systemd/system/tmp-deptest.mount <<EOF
[ Mount]
Where = /tmp/deptest
What = 192.168.0.1:/tmp/mnt
Type = nfs
EOF
systemctl daemon-reload
# with .mount file
check_dependencies
}
2022-05-30 15:50:05 +03:00
test_issue_20329( ) {
local tmpdir unit
tmpdir = " $( mktemp -d) "
unit = $( systemd-escape --suffix mount --path " $tmpdir " )
# Set up test mount unit
2023-02-05 23:41:24 +03:00
cat >/run/systemd/system/" $unit " <<EOF
2022-05-30 15:50:05 +03:00
[ Mount]
What = tmpfs
Where = $tmpdir
Type = tmpfs
Options = defaults,nofail
EOF
# Start the unit
systemctl daemon-reload
systemctl start " $unit "
[ [ " $( systemctl show --property SubState --value " $unit " ) " = "mounted" ] ] || {
echo >& 2 " Test mount \" $unit \" unit isn't mounted "
return 1
}
mountpoint -q " $tmpdir "
trap 'systemctl stop $unit' RETURN
# Trigger the mount ratelimiting
cd " $( mktemp -d) "
mkdir foo
2023-04-07 11:17:15 +03:00
for _ in { 1..50} ; do
2022-05-30 15:50:05 +03:00
mount --bind foo foo
umount foo
done
# Unmount the test mount and start it immediately again via systemd
umount " $tmpdir "
systemctl start " $unit "
# Make sure it is seen as mounted by systemd and it actually is mounted
[ [ " $( systemctl show --property SubState --value " $unit " ) " = "mounted" ] ] || {
echo >& 2 " Test mount \" $unit \" unit isn't in \"mounted\" state "
return 1
}
mountpoint -q " $tmpdir " || {
echo >& 2 " Test mount \" $unit \" is in \"mounted\" state, actually is not mounted "
return 1
}
}
2022-07-01 20:41:40 +03:00
test_issue_23796( ) {
local mount_path mount_mytmpfs
mount_path = " $( command -v mount 2>/dev/null) "
mount_mytmpfs = " ${ mount_path / \/ bin / \/ sbin } .mytmpfs "
cat >" $mount_mytmpfs " <<EOF
#!/bin/bash
sleep ".\$RANDOM"
exec -- $mount_path -t tmpfs tmpfs "\$2"
EOF
chmod +x " $mount_mytmpfs "
mkdir -p /run/systemd/system
cat >/run/systemd/system/tmp-hoge.mount <<EOF
[ Mount]
What = mytmpfs
Where = /tmp/hoge
Type = mytmpfs
EOF
# shellcheck disable=SC2064
trap " rm -f /run/systemd/system/tmp-hoge.mount ' $mount_mytmpfs ' " RETURN
2023-04-07 11:17:15 +03:00
for _ in { 1..10} ; do
2022-07-01 20:41:40 +03:00
systemctl --no-block start tmp-hoge.mount
sleep " . $RANDOM "
systemctl daemon-reexec
sleep 1
if [ [ " $( systemctl is-failed tmp-hoge.mount) " = = "failed" ] ] || \
journalctl -u tmp-hoge.mount -q --grep "but there is no mount" ; then
exit 1
fi
systemctl stop tmp-hoge.mount
done
}
2021-06-08 10:04:35 +03:00
systemd-analyze log-level debug
systemd-analyze log-target journal
NUM_DIRS = 20
2022-03-23 15:35:44 +03:00
# make sure we can handle mounts at very long paths such that mount unit name must be hashed to fall within our unit name limit
LONGPATH = " $( printf " / $( printf "x%0.s" { 1..255} ) %0.s " { 1..7} ) "
LONGMNT = " $( systemd-escape --suffix= mount --path " $LONGPATH " ) "
TS = " $( date '+%H:%M:%S' ) "
mkdir -p " $LONGPATH "
mount -t tmpfs tmpfs " $LONGPATH "
systemctl daemon-reload
# check that unit is active(mounted)
systemctl --no-pager show -p SubState --value " $LONGPATH " | grep -q mounted
# check that relevant part of journal doesn't contain any errors related to unit
[ " $( journalctl -b --since= " $TS " --priority= err | grep -c " $LONGMNT " ) " = "0" ]
# check that we can successfully stop the mount unit
systemctl stop " $LONGPATH "
rm -rf " $LONGPATH "
2021-06-08 10:04:35 +03:00
# mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting
for ( ( i = 0; i < NUM_DIRS; i++) ) ; do
mkdir " /tmp/meow ${ i } "
done
2022-07-08 01:00:42 +03:00
TS = " $( date '+%H:%M:%S' ) "
2021-06-08 10:04:35 +03:00
for ( ( i = 0; i < NUM_DIRS; i++) ) ; do
mount -t tmpfs tmpfs " /tmp/meow ${ i } "
done
systemctl daemon-reload
systemctl list-units -t mount tmp-meow* | grep -q tmp-meow
for ( ( i = 0; i < NUM_DIRS; i++) ) ; do
umount " /tmp/meow ${ i } "
done
2022-07-08 01:00:42 +03:00
# Figure out if we have entered the rate limit state.
# If the infra is slow we might not enter the rate limit state; in that case skip the exit check.
if timeout 2m bash -c " while ! journalctl -u init.scope --since= $TS | grep -q '(mount-monitor-dispatch) entered rate limit'; do sleep 1; done " ; then
timeout 2m bash -c " while ! journalctl -u init.scope --since= $TS | grep -q '(mount-monitor-dispatch) left rate limit'; do sleep 1; done "
2021-06-08 10:04:35 +03:00
fi
2022-07-08 01:00:42 +03:00
# Verify that the mount units are always cleaned up at the end.
# Give some time for units to settle so we don't race between exiting the rate limit state and cleaning up the units.
timeout 2m bash -c 'while systemctl list-units -t mount tmp-meow* | grep -q tmp-meow; do systemctl daemon-reload; sleep 10; done'
2021-06-08 10:04:35 +03:00
2022-07-20 10:56:25 +03:00
# test for issue #19983 and #23552.
test_dependencies
2022-05-30 15:50:05 +03:00
# test that handling of mount start jobs is delayed when /proc/self/mouninfo monitor is rate limited
test_issue_20329
2022-07-01 20:41:40 +03:00
# test for reexecuting with background mount job
test_issue_23796
2021-06-08 10:04:35 +03:00
systemd-analyze log-level info
2022-07-08 01:00:02 +03:00
touch /testok