Add ActivatingConcurrencyMax for slice startup pacing

Introduce Slice.ActivatingConcurrencyMax to limit how many units
within a slice hierarchy may be in activating state concurrently.

Expose the setting over D-Bus, support transient/property parsing,
enforce it during unit start dispatch, and re-check queued starts when
units leave activating state.

Document the new slice option and add a PID1 concurrency test covering
queued startup behavior.
This commit is contained in:
Morteza Pourkazemi
2026-08-03 14:29:07 +09:00
committed by Yu Watanabe
parent 6044c31038
commit 5f0d98e728
9 changed files with 183 additions and 13 deletions
+59
View File
@@ -117,6 +117,65 @@ systemctl start sleepforever3@a.service
systemctl stop concurrency1.slice
systemctl reset-failed
# Test ActivatingConcurrencyMax
cat >/run/systemd/system/concurrency-activating.slice <<EOF
[Slice]
ActivatingConcurrencyMax=2
EOF
cat >/run/systemd/system/slow-start@.service <<EOF
[Service]
Slice=concurrency-activating.slice
# Simulate slow startup
ExecStartPre=/usr/bin/sleep 2
ExecStart=/usr/bin/sleep infinity
EOF
systemctl daemon-reload
# Start 3 services - only 2 should activate concurrently
systemctl --no-block start slow-start@a.service
systemctl --no-block start slow-start@b.service
systemctl --no-block start slow-start@c.service
# Wait for jobs to be dispatched and first two to enter activating
for _ in {1..20}; do
jobs=$(systemctl list-jobs | grep -c "slow-start@.*start" || true)
if [[ "$jobs" -eq 3 ]]; then
activating=$(systemctl list-units --state=activating 'slow-start@*' --no-legend | wc -l)
if [[ "$activating" -eq 2 ]]; then
break
fi
fi
sleep 0.1
done
# Check that exactly 2 are activating (c should be queued)
test "$(systemctl list-jobs | grep -c "slow-start@.*start")" -eq 3
test "$(systemctl show -p ActiveState slow-start@a.service --value)" = "activating"
test "$(systemctl show -p ActiveState slow-start@b.service --value)" = "activating"
test "$(systemctl show -p ActiveState slow-start@c.service --value)" = "inactive"
# Wait for a and b to finish starting, then c to start and finish
# a,b take ~2s to activate, then c starts and takes ~2s more
sleep 5
# Now all should be active (c started when a/b finished activating)
systemctl is-active slow-start@a.service
systemctl is-active slow-start@b.service
systemctl is-active slow-start@c.service
# Cleanup
systemctl stop concurrency-activating.slice
systemctl reset-failed
rm /run/systemd/system/concurrency-activating.slice
rm /run/systemd/system/slow-start@.service
systemctl daemon-reload
# Final cleanup of original tests
systemctl reset-failed
rm /run/systemd/system/concurrency1.slice
rm /run/systemd/system/concurrency1-concurrency2.slice
rm /run/systemd/system/concurrency1-concurrency3.slice