1#!/usr/bin/env bash
2# SPDX-License-Identifier: LGPL-2.1-or-later
3set -eux
4set -o pipefail
5
6systemd-analyze log-level debug
7systemd-analyze log-target journal
8
9NUM_DIRS=20
10
11# 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
12LONGPATH="$(printf "/$(printf "x%0.s" {1..255})%0.s" {1..7})"
13LONGMNT="$(systemd-escape --suffix=mount --path "$LONGPATH")"
14TS="$(date '+%H:%M:%S')"
15
16mkdir -p "$LONGPATH"
17mount -t tmpfs tmpfs "$LONGPATH"
18systemctl daemon-reload
19
20# check that unit is active(mounted)
21systemctl --no-pager show -p SubState --value "$LONGPATH" | grep -q mounted
22
23# check that relevant part of journal doesn't contain any errors related to unit
24[ "$(journalctl -b --since="$TS" --priority=err | grep -c "$LONGMNT")" = "0" ]
25
26# check that we can successfully stop the mount unit
27systemctl stop "$LONGPATH"
28rm -rf "$LONGPATH"
29
30# mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting
31
32for ((i = 0; i < NUM_DIRS; i++)); do
33    mkdir "/tmp/meow${i}"
34done
35
36for ((i = 0; i < NUM_DIRS; i++)); do
37    mount -t tmpfs tmpfs "/tmp/meow${i}"
38done
39
40systemctl daemon-reload
41systemctl list-units -t mount tmp-meow* | grep -q tmp-meow
42
43for ((i = 0; i < NUM_DIRS; i++)); do
44    umount "/tmp/meow${i}"
45done
46
47# figure out if we have entered the rate limit state
48
49entered_rl=0
50exited_rl=0
51timeout="$(date -ud "2 minutes" +%s)"
52while [[ $(date -u +%s) -le ${timeout} ]]; do
53    if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) entered rate limit"; then
54        entered_rl=1
55        break
56    fi
57    sleep 5
58done
59
60# if the infra is slow we might not enter the rate limit state; in that case skip the exit check
61
62if [ "${entered_rl}" = "1" ]; then
63    exited_rl=0
64    timeout="$(date -ud "2 minutes" +%s)"
65    while [[ $(date -u +%s) -le ${timeout} ]]; do
66        if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) left rate limit"; then
67            exited_rl=1
68            break
69        fi
70        sleep 5
71    done
72
73    if [ "${exited_rl}" = "0" ]; then
74        exit 24
75    fi
76fi
77
78# give some time for units to settle so we don't race between exiting the rate limit state and cleaning up the units
79
80sleep 60
81systemctl daemon-reload
82sleep 60
83
84# verify that the mount units are always cleaned up at the end
85
86if systemctl list-units -t mount tmp-meow* | grep -q tmp-meow; then
87    exit 42
88fi
89
90systemd-analyze log-level info
91
92echo OK >/testok
93
94exit 0
95