b7dd4d
From 2b390a10d826f060a672d9f01c6ad43714691274 Mon Sep 17 00:00:00 2001
62b62a
From: Anita Zhang <the.anitazha@gmail.com>
62b62a
Date: Tue, 8 Jun 2021 00:04:35 -0700
62b62a
Subject: [PATCH] test: add extended test for triggering mount rate limit
62b62a
62b62a
It's hard to trigger the failure to exit the rate limit state in
62b62a
isolation as it needs multiple event sources in order to show that it
62b62a
gets stuck in the queue. Hence why this is an extended test.
62b62a
62b62a
(cherry picked from commit 0c81900965a72b29eb76e0737ed899b925ee75b6)
62b62a
b7dd4d
Related: #1940973
62b62a
---
62b62a
 test/TEST-60-MOUNT-RATELIMIT/Makefile     |  1 +
62b62a
 test/TEST-60-MOUNT-RATELIMIT/test.sh      | 48 +++++++++++++++
62b62a
 test/TEST-60-MOUNT-RATELIMIT/testsuite.sh | 73 +++++++++++++++++++++++
62b62a
 3 files changed, 122 insertions(+)
62b62a
 create mode 120000 test/TEST-60-MOUNT-RATELIMIT/Makefile
62b62a
 create mode 100755 test/TEST-60-MOUNT-RATELIMIT/test.sh
62b62a
 create mode 100755 test/TEST-60-MOUNT-RATELIMIT/testsuite.sh
62b62a
62b62a
diff --git a/test/TEST-60-MOUNT-RATELIMIT/Makefile b/test/TEST-60-MOUNT-RATELIMIT/Makefile
62b62a
new file mode 120000
62b62a
index 0000000000..e9f93b1104
62b62a
--- /dev/null
62b62a
+++ b/test/TEST-60-MOUNT-RATELIMIT/Makefile
62b62a
@@ -0,0 +1 @@
62b62a
+../TEST-01-BASIC/Makefile
62b62a
\ No newline at end of file
62b62a
diff --git a/test/TEST-60-MOUNT-RATELIMIT/test.sh b/test/TEST-60-MOUNT-RATELIMIT/test.sh
62b62a
new file mode 100755
62b62a
index 0000000000..e3c9288546
62b62a
--- /dev/null
62b62a
+++ b/test/TEST-60-MOUNT-RATELIMIT/test.sh
62b62a
@@ -0,0 +1,48 @@
62b62a
+#!/usr/bin/env bash
62b62a
+set -e
62b62a
+TEST_DESCRIPTION="Test that mount/unmount storms can enter/exit rate limit state and will not leak units"
62b62a
+
62b62a
+. $TEST_BASE_DIR/test-functions
62b62a
+
62b62a
+test_setup() {
62b62a
+    create_empty_image
62b62a
+    mkdir -p $TESTDIR/root
62b62a
+    mount ${LOOPDEV}p1 $TESTDIR/root
62b62a
+
62b62a
+    (
62b62a
+        LOG_LEVEL=5
62b62a
+        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
62b62a
+
62b62a
+        setup_basic_environment
62b62a
+
62b62a
+        # mask some services that we do not want to run in these tests
62b62a
+        ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
62b62a
+        ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
62b62a
+        ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
62b62a
+        ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
62b62a
+        ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
62b62a
+        ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service
62b62a
+
62b62a
+        # setup the testsuite service
62b62a
+        cat >$initdir/etc/systemd/system/testsuite.service <
62b62a
+[Unit]
62b62a
+Description=Testsuite service
62b62a
+
62b62a
+[Service]
62b62a
+ExecStart=/bin/bash -x /testsuite.sh
62b62a
+Type=oneshot
62b62a
+StandardOutput=tty
62b62a
+StandardError=tty
62b62a
+NotifyAccess=all
62b62a
+EOF
62b62a
+        cp testsuite.sh $initdir/
62b62a
+
62b62a
+        setup_testsuite
62b62a
+    ) || return 1
62b62a
+    setup_nspawn_root
62b62a
+
62b62a
+    ddebug "umount $TESTDIR/root"
62b62a
+    umount $TESTDIR/root
62b62a
+}
62b62a
+
62b62a
+do_test "$@"
62b62a
diff --git a/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh
62b62a
new file mode 100755
62b62a
index 0000000000..8158754667
62b62a
--- /dev/null
62b62a
+++ b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh
62b62a
@@ -0,0 +1,73 @@
62b62a
+#!/usr/bin/env bash
62b62a
+set -eux
62b62a
+set -o pipefail
62b62a
+
62b62a
+systemd-analyze log-level debug
62b62a
+systemd-analyze log-target journal
62b62a
+
62b62a
+NUM_DIRS=20
62b62a
+
62b62a
+# mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting
62b62a
+
62b62a
+for ((i = 0; i < NUM_DIRS; i++)); do
62b62a
+    mkdir "/tmp/meow${i}"
62b62a
+done
62b62a
+
62b62a
+for ((i = 0; i < NUM_DIRS; i++)); do
62b62a
+    mount -t tmpfs tmpfs "/tmp/meow${i}"
62b62a
+done
62b62a
+
62b62a
+systemctl daemon-reload
62b62a
+systemctl list-units -t mount tmp-meow* | grep -q tmp-meow
62b62a
+
62b62a
+for ((i = 0; i < NUM_DIRS; i++)); do
62b62a
+    umount "/tmp/meow${i}"
62b62a
+done
62b62a
+
62b62a
+# figure out if we have entered the rate limit state
62b62a
+
62b62a
+exited_rl=0
62b62a
+timeout="$(date -ud "2 minutes" +%s)"
62b62a
+while [[ $(date -u +%s) -le ${timeout} ]]; do
62b62a
+    if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) entered rate limit"; then
62b62a
+        entered_rl=1
62b62a
+        break
62b62a
+    fi
62b62a
+    sleep 5
62b62a
+done
62b62a
+
62b62a
+# if the infra is slow we might not enter the rate limit state; in that case skip the exit check
62b62a
+
62b62a
+if [ "${entered_rl}" = "1" ]; then
62b62a
+    exited_rl=0
62b62a
+    timeout="$(date -ud "2 minutes" +%s)"
62b62a
+    while [[ $(date -u +%s) -le ${timeout} ]]; do
62b62a
+        if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) left rate limit"; then
62b62a
+            exited_rl=1
62b62a
+            break
62b62a
+        fi
62b62a
+        sleep 5
62b62a
+    done
62b62a
+
62b62a
+    if [ "${exited_rl}" = "0" ]; then
62b62a
+        exit 24
62b62a
+    fi
62b62a
+fi
62b62a
+
62b62a
+# give some time for units to settle so we don't race between exiting the rate limit state and cleaning up the units
62b62a
+
62b62a
+sleep 60
62b62a
+systemctl daemon-reload
62b62a
+sleep 60
62b62a
+
62b62a
+# verify that the mount units are always cleaned up at the end
62b62a
+
62b62a
+if systemctl list-units -t mount tmp-meow* | grep -q tmp-meow; then
62b62a
+    exit 42
62b62a
+fi
62b62a
+
62b62a
+systemd-analyze log-level info
62b62a
+
62b62a
+echo OK >/testok
62b62a
+
62b62a
+exit 0