File: TEST-60-MOUNT-RATELIMIT.sh

package info (click to toggle)
systemd 259.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 113,388 kB
  • sloc: ansic: 727,211; xml: 121,125; python: 36,732; sh: 34,990; cpp: 946; makefile: 278; awk: 102; lisp: 13; sed: 1
file content (180 lines) | stat: -rwxr-xr-x 5,311 bytes parent folder | download | duplicates (2)
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