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
2024-10-16 16:32:09 +03:00
# shellcheck source=test/units/test-control.sh
. " $( dirname " $0 " ) " /test-control.sh
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
2024-05-11 20:17:13 +03:00
rm -f /tmp/TEST-60-MOUNT-RATELIMIT-dependencies-0.img
rm -f /tmp/TEST-60-MOUNT-RATELIMIT-dependencies-1.img
2022-07-20 10:56:25 +03:00
rm -f /run/systemd/system/tmp-deptest.mount
systemctl daemon-reload
return 0
)
setup_loop( ) {
2024-05-11 20:17:13 +03:00
truncate -s 30m " /tmp/TEST-60-MOUNT-RATELIMIT-dependencies- ${ 1 ? } .img "
sfdisk --wipe= always " /tmp/TEST-60-MOUNT-RATELIMIT-dependencies- ${ 1 ? } .img " <<EOF
2022-07-20 10:56:25 +03:00
label:gpt
name = " loop ${ 1 ? } -part1 "
EOF
2024-05-11 20:17:13 +03:00
LOOP = $( losetup -P --show -f " /tmp/TEST-60-MOUNT-RATELIMIT-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
2024-10-16 15:17:15 +03:00
timeout 10 bash -c 'until systemctl -q is-active tmp-deptest.mount; do sleep .1; done'
2022-07-20 10:56:25 +03:00
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 "
2024-10-16 15:17:15 +03:00
systemctl stop tmp-deptest.mount
2022-07-20 10:56:25 +03:00
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
2024-10-16 15:17:15 +03:00
timeout 10 bash -c 'until systemctl -q is-active tmp-deptest.mount; do sleep .1; done'
2022-07-20 10:56:25 +03:00
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 "
2024-10-16 15:17:15 +03:00
systemctl stop tmp-deptest.mount
2022-07-20 10:56:25 +03:00
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
2024-10-16 15:17:15 +03:00
timeout 10 bash -c 'until systemctl -q is-active tmp-deptest.mount; do sleep .1; done'
2022-07-20 10:56:25 +03:00
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 "
2024-10-16 15:17:15 +03:00
systemctl stop tmp-deptest.mount
2022-07-20 10:56:25 +03:00
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
}
2024-10-16 16:32:09 +03:00
testcase_dependencies( ) {
# test for issue #19983 and #23552.
2022-07-20 10:56:25 +03:00
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
}
2024-10-16 16:32:09 +03:00
testcase_issue_20329( ) {
# test that handling of mount start jobs is delayed when /proc/self/mouninfo monitor is rate limited
2022-05-30 15:50:05 +03:00
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
}
}
2024-10-16 16:32:09 +03:00
testcase_issue_23796( ) {
# test for reexecuting with background mount job
2024-05-19 20:34:17 +03:00
local mount_path mount_mytmpfs since
2022-07-01 20:41:40 +03:00
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
2024-05-19 20:34:17 +03:00
journalctl --sync
since = " $( date '+%H:%M:%S' ) "
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" ] ] || \
2024-05-19 20:34:17 +03:00
journalctl --since= " $since " -u tmp-hoge.mount -q --grep "but there is no mount" ; then
2022-07-01 20:41:40 +03:00
exit 1
fi
systemctl stop tmp-hoge.mount
done
}
2024-10-16 16:32:09 +03:00
testcase_long_path( ) {
local long_path long_mnt ts
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +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
long_path = " $( printf " / $( printf "x%0.s" { 1..255} ) %0.s " { 1..7} ) "
long_mnt = " $( systemd-escape --suffix= mount --path " $long_path " ) "
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +03:00
journalctl --sync
ts = " $( date '+%H:%M:%S' ) "
2024-05-19 20:34:17 +03:00
2024-10-16 16:32:09 +03:00
mkdir -p " $long_path "
mount -t tmpfs tmpfs " $long_path "
systemctl daemon-reload
2022-03-23 15:35:44 +03:00
2024-10-16 16:32:09 +03:00
# check that unit is active(mounted)
systemctl --no-pager show -p SubState --value " $long_path " | grep -q mounted
2022-03-23 15:35:44 +03:00
2024-10-16 16:32:09 +03:00
# check that relevant part of journal doesn't contain any errors related to unit
[ " $( journalctl -b --since= " $ts " --priority= err | grep -c " $long_mnt " ) " = "0" ]
2022-03-23 15:35:44 +03:00
2024-10-16 16:32:09 +03:00
# check that we can successfully stop the mount unit
systemctl stop " $long_path "
rm -rf " $long_path "
}
2022-03-23 15:35:44 +03:00
2024-10-16 16:32:09 +03:00
testcase_mount_ratelimit( ) {
local num_dirs = 20
local ts i
2022-03-23 15:35:44 +03:00
2024-10-16 16:32:09 +03:00
# mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +03:00
for ( ( i = 0; i < num_dirs; i++) ) ; do
mkdir " /tmp/meow ${ i } "
done
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +03:00
# The following loop may produce many journal entries.
# Let's process all pending entries before testing.
journalctl --sync
ts = " $( date '+%H:%M:%S' ) "
2022-07-08 01:00:42 +03:00
2024-10-16 16:32:09 +03:00
for ( ( i = 0; i < num_dirs; i++) ) ; do
mount -t tmpfs tmpfs " /tmp/meow ${ i } "
done
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +03:00
systemctl daemon-reload
systemctl list-units -t mount tmp-meow* | grep -q tmp-meow
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +03:00
for ( ( i = 0; i < num_dirs; i++) ) ; do
umount " /tmp/meow ${ i } "
done
2021-06-08 10:04:35 +03:00
2024-10-16 16:32:09 +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.
set +o pipefail
2024-05-19 20:34:17 +03:00
journalctl --sync
2024-10-16 16:32:09 +03:00
if timeout 2m journalctl -u init.scope --since= " $ts " -n all --follow | grep -m 1 -q -F '(mount-monitor-dispatch) entered rate limit' ; then
journalctl --sync
timeout 2m journalctl -u init.scope --since= " $ts " -n all --follow | grep -m 1 -q -F '(mount-monitor-dispatch) left rate limit'
fi
set -o pipefail
2022-07-20 10:56:25 +03:00
2024-10-16 16:32:09 +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'
}
2022-05-30 15:50:05 +03:00
2024-10-16 16:32:09 +03:00
systemd-analyze log-level debug
systemd-analyze log-target journal
2022-07-01 20:41:40 +03:00
2024-10-16 16:34:48 +03:00
mkdir -p /run/systemd/journald.conf.d
cat >/run/systemd/journald.conf.d/99-ratelimit.conf <<EOF
[ Journal]
RateLimitBurst = 0
EOF
systemctl restart systemd-journald.service
2024-10-16 16:32:09 +03:00
run_testcases
2021-06-08 10:04:35 +03:00
2022-07-08 01:00:02 +03:00
touch /testok