1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
testcase_issue_20329() {
# test that handling of mount start jobs is delayed when /proc/self/mouninfo monitor is rate limited
local tmpdir unit
tmpdir="$(mktemp -d)"
unit=$(systemd-escape --suffix mount --path "$tmpdir")
# Set up test mount unit
cat >/run/systemd/system/"$unit" <<EOF
[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
for _ in {1..50}; do
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
}
}
testcase_issue_23796() {
# test for reexecuting with background mount job
local mount_path mount_mytmpfs since
mount_path="$(command -v mount 2>/dev/null)"
mount_mytmpfs="${mount_path/\/bin/\/sbin}.mytmpfs"
cat >"$mount_mytmpfs" <<EOF
#!/usr/bin/env 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
journalctl --sync
since="$(date '+%H:%M:%S')"
for _ in {1..10}; do
systemctl --no-block start tmp-hoge.mount
sleep ".$RANDOM"
systemctl daemon-reexec
sleep 1
if [[ "$(systemctl is-failed tmp-hoge.mount)" == "failed" ]] ||
journalctl --since="$since" -u tmp-hoge.mount -q --grep "but there is no mount"; then
exit 1
fi
systemctl stop tmp-hoge.mount
done
}
testcase_long_path() {
local long_path long_mnt ts
# 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")"
journalctl --sync
ts="$(date '+%H:%M:%S')"
mkdir -p "$long_path"
mount -t tmpfs tmpfs "$long_path"
systemctl daemon-reload
# check that unit is active(mounted)
systemctl --no-pager show -p SubState --value "$long_path" | grep mounted >/dev/null
# 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" ]
# check that we can successfully stop the mount unit
systemctl stop "$long_path"
rm -rf "$long_path"
}
testcase_mount_ratelimit() {
local num_dirs=20
local ts i
# 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
# The following loop may produce many journal entries.
# Let's process all pending entries before testing.
journalctl --sync
ts="$(date '+%H:%M:%S')"
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 tmp-meow >/dev/null
for ((i = 0; i < num_dirs; i++)); do
umount "/tmp/meow${i}"
done
# 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.
journalctl --sync
if timeout 2m bash -c "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 bash -c "journalctl -u init.scope --since='$ts' -n all --follow | grep -m 1 -q -F '(mount-monitor-dispatch) left rate limit'"
fi
# 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 tmp-meow >/dev/null; do systemctl daemon-reload; sleep 10; done'
}
mkdir -p /run/systemd/journald.conf.d
cat >/run/systemd/journald.conf.d/99-ratelimit.conf <<EOF
[Journal]
RateLimitBurst=0
EOF
systemctl reload systemd-journald.service
run_testcases
touch /testok
|