From 481279c9bffd19e32c8f3299897e9b63fc5a24aa Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Wed, 20 May 2026 10:26:58 +0200 Subject: [PATCH] packaging/systemd: ship daedalus-v4l2.service + modules-load drop-in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Canonical location for the systemd unit + module-autoload conf, referenced by both arch/daedalus-v4l2 and debian/daedalus-v4l2 in marfrit-packages. Was a real gap in the original packaging: postinst installed the daemon binary but nothing started it, so the libva path got REQ_DECODE messages with nobody listening on /dev/daedalus-v4l2 and timed out. packaging/systemd/daedalus-v4l2.service: - Type=simple, ExecStart=/usr/bin/daedalus_v4l2_daemon daemon - After=systemd-modules-load.service + ConditionPathExists= /dev/daedalus-v4l2 (so it only starts when the kernel module is loaded; doesn't false-fire on non-daedalus hosts that happen to have the package installed) - Restart=on-failure, RestartSec=2 - MemoryHigh=128M / MemoryMax=256M (Phase 8.9 stress run showed RSS settling around 25 MiB; leaves headroom) - Hardening: NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, ProtectKernel*, SystemCallFilter=@system-service. PrivateDevices=false because we DO need /dev/daedalus-v4l2 packaging/systemd/daedalus-v4l2.modules-load: - Drops to /etc/modules-load.d/daedalus-v4l2.conf so the kernel module loads before the .service unit fires. Both files are picked up by the package recipes (next bump in marfrit-packages) — neither lives in /usr/lib/systemd/system or /etc/modules-load.d until the .deb / .pkg installs them. Co-Authored-By: Claude Opus 4.7 (1M context) --- packaging/systemd/daedalus-v4l2.modules-load | 6 ++ packaging/systemd/daedalus-v4l2.service | 66 ++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 packaging/systemd/daedalus-v4l2.modules-load create mode 100644 packaging/systemd/daedalus-v4l2.service diff --git a/packaging/systemd/daedalus-v4l2.modules-load b/packaging/systemd/daedalus-v4l2.modules-load new file mode 100644 index 0000000..e7c22c2 --- /dev/null +++ b/packaging/systemd/daedalus-v4l2.modules-load @@ -0,0 +1,6 @@ +# /etc/modules-load.d/daedalus-v4l2.conf +# +# Load the daedalus_v4l2 kernel module at boot so /dev/daedalus-v4l2 +# + /dev/videoNN (V4L2 m2m decoder) + /dev/mediaNN (request API) +# come up before the daedalus-v4l2.service unit fires. +daedalus_v4l2 diff --git a/packaging/systemd/daedalus-v4l2.service b/packaging/systemd/daedalus-v4l2.service new file mode 100644 index 0000000..e9e75bb --- /dev/null +++ b/packaging/systemd/daedalus-v4l2.service @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# daedalus-v4l2 userspace decoder daemon. +# +# Pairs with the daedalus_v4l2 kernel module (DKMS-built into +# /lib/modules/.../updates/dkms/daedalus_v4l2.ko). When the +# module loads it creates /dev/daedalus-v4l2 (chardev bridge). +# This unit starts the userspace daemon that holds the chardev +# open and answers REQ_DECODE requests with FFmpeg-software +# decode + dmabuf-back. +# +# Without the daemon running, libva / V4L2 clients can S_FMT / +# REQBUFS / QBUF against /dev/videoNN but the decode never +# returns (device_run sends REQ_DECODE into the chardev and +# nothing answers). Always-on is the right disposition. + +[Unit] +Description=daedalus-v4l2 userspace decoder daemon +Documentation=https://git.reauktion.de/reauktion/daedalus-v4l2 + +# Wait until /dev/daedalus-v4l2 actually exists. systemd +# auto-derives the device unit name from the path. The kernel +# module is loaded via /etc/modules-load.d/daedalus-v4l2.conf +# (see daedalus-v4l2.modules-load) earlier in the boot sequence. +After=systemd-modules-load.service +Wants=systemd-modules-load.service +ConditionPathExists=/dev/daedalus-v4l2 + +[Service] +Type=simple +ExecStart=/usr/bin/daedalus_v4l2_daemon daemon + +# Daemon needs read+write on the chardev (created mode 0660 by +# the kernel module, owner root:video). Run as root for simplicity; +# can be relaxed to a daedalus system user with `video` supplementary +# group when we add the user. +User=root + +# Recover from crashes. RestartSec=2 picks a small but non-zero +# backoff so a tight crash-loop doesn't burn CPU. +Restart=on-failure +RestartSec=2 + +# Resource hygiene. Daemon's RSS settles around 25 MiB (per +# Phase 8.9 stress test); the cap is well above that to leave +# headroom for FFmpeg internal state on large frames. +MemoryHigh=128M +MemoryMax=256M + +# Hardening — keep what the daemon doesn't need locked down. +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +PrivateDevices=false # we need /dev/daedalus-v4l2 +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true +RestrictNamespaces=true +RestrictRealtime=true +LockPersonality=true +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERM + +[Install] +WantedBy=multi-user.target