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