#!/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" <&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" </run/systemd/system/tmp-hoge.mount </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 # We entered the rate limit state. Verify that the manager leaves it again on its own and # processes the pending mount table changes, i.e. that all the mount units we unmounted above are # cleaned up automatically, without daemon-reload. timeout 2m bash -c 'while systemctl list-units -t mount tmp-meow* | grep tmp-meow >/dev/null; do sleep 1; done' else # We never entered the rate limit state (e.g. on slow infra), so the recovery path above is not # being exercised. Just make sure the mount units are cleaned up, nudging the manager if needed. timeout 2m bash -c 'while systemctl list-units -t mount tmp-meow* | grep tmp-meow >/dev/null; do systemctl daemon-reload; sleep 10; done' fi } mkdir -p /run/systemd/journald.conf.d cat >/run/systemd/journald.conf.d/99-ratelimit.conf <