Files
finit/system/10-hotplug.conf.in
Joachim Wiberg 96c5b4b031 doc: document the provides setting
The migration guide told anyone holding the repeated-stanza idiom for a
per-platform service to split the variants across files or stay on the
line-based format, because a block title is an identity and the
variants have to share one barrier.  provides is the answer, so the
guide converts that shape now instead of routing around it, and the
header of 10-hotplug.conf.in no longer points at the workaround.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-05 17:59:09 +02:00

162 lines
5.7 KiB
Plaintext

# System hotplug handled by udev, mdevd, or mdev (preferred order)
#
# Your system usually has either udevd, mdev, or mdevd. They probe the system
# for devices, loading modules and any firmware needed. Since the bootstrap
# often needs to be synchronized carefully, we suggest using your system log
# daemon as the barrier for all other services. E.g.:
#
# service syslogd {
# description = "System log daemon"
# runlevel = "S0123456789"
# if = "udevd"
# conditions = { "run/udevadm:5/success" }
# command = "syslogd -F"
# }
#
# This provides a pid/syslogd condition that can act as a barrier for all
# other services. Notice the `if` setting: the condition for starting
# syslogd is only considered if either udevd or mdev (service) is loaded and
# is guaranteed to run after each respective run stanza have completed.
#
# The mdev and mdevd systems wait for a different coldplug condition, so they
# need their own block, and a block title is a service identity: two blocks
# titled syslogd in one file are two declarations of one service, which Finit
# rejects. Give each variant its own title and name the shared barrier that
# everything downstream waits for:
#
# service syslogd:udev {
# if = "udevd"
# conditions = { "run/udevadm:5/success" }
# provides = "pid/syslogd"
# command = "syslogd -F"
# }
# service syslogd:mdev {
# if = "mdev"
# conditions = { "run/coldplug/success" }
# provides = "pid/syslogd"
# command = "syslogd -F"
# }
#
# Override this file by copying it to /etc/finit.d/, using the same name, then
# change the contents any way you like, it can even be empty.
# Check for systemd-udevd and eudev, if we find both, we opt for the latter.
# Both spellings are candidates for the same service, Finit starts the first
# one it finds. A leading '-' on the last says it is fine if neither is
# installed, we fall through to mdevd or mdev below.
service udevd {
description = "Device event daemon (udev)"
runlevel = "S12345789"
notify = "none"
envfile = "-/etc/default/udevd"
pidfile = "udevd"
pidfile-create = true
log { }
cgroup system { name = "udevd" }
command = { "/lib/systemd/systemd-udevd $UDEVD_ARGS",
"-udevd $UDEVD_ARGS" }
}
# Wait for udevd to start, then trigger coldplug events and module loading.
# The last 'settle' call waits for it to finalize processing all uevents.
run udevadm:1 {
runlevel = "S"
if = "udevd"
conditions = { "service/udevd/ready" }
log { }
cgroup init { name = "udevadm" }
command = "-udevadm settle -t 0"
}
run udevadm:2 {
runlevel = "S"
if = "udevd"
conditions = { "service/udevd/ready" }
log { }
cgroup init { name = "udevadm" }
command = "-udevadm control --reload"
}
run udevadm:3 {
description = "Requesting device events"
runlevel = "S"
if = "udevd"
conditions = { "service/udevd/ready" }
log { }
cgroup init { name = "udevadm" }
command = "-udevadm trigger -c add -t devices"
}
run udevadm:4 {
description = "Requesting subsystem events"
runlevel = "S"
if = "udevd"
conditions = { "service/udevd/ready" }
log { }
cgroup init { name = "udevadm" }
command = "-udevadm trigger -c add -t subsystems"
}
run udevadm:5 {
description = "Waiting for udev to finish"
runlevel = "S"
if = "udevd"
conditions = { "service/udevd/ready" }
log { }
cgroup init { name = "udevadm" }
command = "-udevadm settle -t 30"
}
# If udevd is not available, check for mdevd. Unlike plain 'mdev -df', the
# mdevd-coldplug process exits when mdevd has completed. So the condition
# <run/mdevd-coldplug/success> can be relied on as a barrier for services
# that, e.g., need to probe for switchcore ports or PHYs that require
# firmware loading before they show up.
service mdevd {
description = "Device event daemon (mdevd)"
runlevel = "S12345789"
if = "!udevd"
conflicts = { "udevd", "mdev" }
notify = "s6"
cgroup init { name = "mdevd" }
command = "-mdevd -O 4 -D %n"
}
# NOTE: this block is named for its command, so its barrier condition is
# <run/mdevd-coldplug/success>, not the <run/coldplug/success> the
# plain mdev stanza below provides. The legacy line spelled the
# name inside the cgroup argument, where it names the cgroup leaf
# rather than the service, and the two paths have differed ever
# since. Left as it was so boot ordering does not change.
run mdevd-coldplug {
description = "Cold plugging system"
runlevel = "S"
conflicts = { "udevd", "mdev" }
conditions = { "service/mdevd/ready" }
cgroup init { name = "coldplug" }
command = "-mdevd-coldplug"
}
# If neither udevd or mdevd are available, fall back to mdev. The new daemon
# mode calls `mdev -s` internally but does not create a PID file when that is
# done, so synchronization with coldplug is fragile.
service mdev {
description = "Device event daemon (mdev)"
runlevel = "S12345789"
if = "!udevd,!mdevd"
conflicts = { "udevd", "mdevd" }
notify = "none"
cgroup init { name = "mdev" }
command = "-mdev -df -S"
}
# Trigger a replay of all uevents from boot, before userspace was up and the
# filesystem mounted. Compared to udevd, we don't know when 'mdev -df' has
# finished processing all events, i.e., depending on <run/coldplug/success> is
# not an indicator of all devices having been (re)discovered and fully set up.
run coldplug {
description = "Cold plugging system"
runlevel = "S"
if = "mdev"
conflicts = { "udevd", "mdevd" }
conditions = { "service/mdev/running" }
cgroup init {}
command = "-@pkglibexecdir@/coldplug"
}