A Plex section scan walked 50k files at ~850 r/s and nothing bounded it. `IOWeight=` in a quadlet looks like the fix and does nothing: systemd delegates `cpu memory pids` to user@.service and NOT io, and it drops a resource line it cannot honour without a word — the container boots healthy and its cgroup has no io.weight file at all. Same family as RequiresMountsFor= (inert in the user manager) and ConditionPathIsMountPoint= (fail-dead). Place the two system drop-ins that make the controller reachable (user.slice IOAccounting=yes puts io in user.slice/cgroup.subtree_control, measured immediately; user@1000.service DelegateControllers gains io and lands at the next reboot, because restarting the user manager would kill every rootless container on the host), then ask for the share: IOWeight=10 on jellyfin and plex. 10 is a convention, not a measured optimum — proportional share, only bites under contention, only requirement is far below the default 100. ensure_user_io_delegate places both from git and prints NOTE: io is not delegated … inert until the next reboot, so the quadlet line never reads as live config. Verified on the host: subtree_control flipped to `cpu io memory pids`, the drop-in is attached and parsed (systemctl cat), and the podman 5.7 generator emits IOWeight=10 for both units (bare key; UnitConfigItem= not needed). Two limits recorded instead of hidden: a container's weight covers its whole cgroup (scan and playback share it), and the comparison happens inside user.slice, so it cannot push a rootless unit below a root unit such as frank-archon — that pairing is user.slice's own weight, a separate call. Docs: Quadlet Lifecycle 4b (the three-command read of the chain), Pi-hole (all rootless containers share one 10.0.2.100, so one chatty container throttles DNS for the host — 8 events today), E2E Suite gotcha 7 (the gate depends on the runner's resolver: 21 reds on a lost wired link, 37/37 minutes later). Seam: an in-repo IOWeight= may only exist when both drop-ins exist AND the deployer places them. ./tests/run.sh: 789 ok, exit 0.
13 lines
700 B
Plaintext
13 lines
700 B
Plaintext
# The system manager gives the user manager cpu/memory/pids by default (systemd
|
|
# 259: `systemctl show user@1000.service -p DelegateControllers` → `cpu memory
|
|
# pids`). Without `io` in that set no `io.weight` file can exist anywhere below
|
|
# `user.slice`, so `IOWeight=` in a rootless quadlet is silently inert — the same
|
|
# class of trap as `RequiresMountsFor=`. Granting the controller here is what
|
|
# makes the media servers' I/O share real.
|
|
#
|
|
# Inert until `user@1000.service` starts again, i.e. the next reboot (restarting
|
|
# it would kill every rootless container on the host). Verify after the reboot
|
|
# with the check in [[Quadlet Lifecycle]].
|
|
[Service]
|
|
DelegateControllers=cpu memory pids io
|