udev: support soft-reboot (#37222)
This commit is contained in:
@@ -2357,6 +2357,8 @@ static void socket_enter_running(Socket *s, int cfd_in) {
|
||||
}
|
||||
|
||||
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, &error, /* ret = */ NULL);
|
||||
if (r == -EDEADLK)
|
||||
return (void) log_unit_debug_errno(UNIT(s), r, "Failed to queue service startup job, ignoring: %s", bus_error_message(&error, r));
|
||||
if (r < 0)
|
||||
goto queue_error;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,56 @@ if [[ -L /run/nextroot ]]; then
|
||||
rm -f /run/nextroot
|
||||
fi
|
||||
|
||||
trigger_uevent() {
|
||||
local rule=/run/udev/rules.d/99-softreboot.rules
|
||||
|
||||
if [[ ! -f "$rule" ]]; then
|
||||
mkdir -p /run/udev/rules.d
|
||||
cat >"$rule" <<EOF
|
||||
SUBSYSTEM!="mem", GOTO="end"
|
||||
KERNEL!="null", GOTO="end"
|
||||
ACTION=="remove", GOTO="end"
|
||||
|
||||
IMPORT{db}="HISTORY"
|
||||
IMPORT{program}="/bin/bash -c 'systemctl show --property=SoftRebootsCount'"
|
||||
ENV{HISTORY}+="%E{ACTION}_%E{SEQNUM}_%E{SoftRebootsCount}"
|
||||
|
||||
LABEL="end"
|
||||
EOF
|
||||
udevadm control --reload
|
||||
fi
|
||||
|
||||
systemd-run \
|
||||
--unit=TEST-82-SOFTREBOOT-trigger.service \
|
||||
--property DefaultDependencies=no \
|
||||
--property Conflicts=soft-reboot.target \
|
||||
--property Before=soft-reboot.target \
|
||||
--property Before=systemd-soft-reboot.service \
|
||||
--property Before=systemd-udevd.service \
|
||||
--property RemainAfterExit=yes \
|
||||
--property 'ExecStop=udevadm trigger --action bind /dev/null' \
|
||||
true
|
||||
}
|
||||
|
||||
check_device_property() {
|
||||
local expected_count=${1:?}
|
||||
|
||||
udevadm info --no-pager /dev/null
|
||||
|
||||
local action seqnum softreboot_count
|
||||
local previous_seqnum=0
|
||||
local count=0
|
||||
while read -r action seqnum softreboot_count; do
|
||||
test "$seqnum" -gt "$previous_seqnum"
|
||||
assert_eq "$action" "bind"
|
||||
assert_eq "$softreboot_count" "$((++count))"
|
||||
|
||||
previous_seqnum="$seqnum"
|
||||
done < <(udevadm info -q property --property=HISTORY --value /dev/null | sed -e 's/ /\n/g; s/_/ /g')
|
||||
|
||||
assert_eq "$count" "$expected_count"
|
||||
}
|
||||
|
||||
systemd-analyze log-level debug
|
||||
|
||||
export SYSTEMD_LOG_LEVEL=debug
|
||||
@@ -70,6 +120,8 @@ if [ -f /run/TEST-82-SOFTREBOOT.touch3 ]; then
|
||||
journalctl -o short-monotonic --no-hostname --grep '(will soft-reboot|KILL|corrupt)'
|
||||
assert_eq "$(journalctl -q -o short-monotonic -u systemd-journald.service --grep 'corrupt')" ""
|
||||
|
||||
check_device_property 3
|
||||
|
||||
# All succeeded, exit cleanly now
|
||||
|
||||
elif [ -f /run/TEST-82-SOFTREBOOT.touch2 ]; then
|
||||
@@ -110,6 +162,9 @@ elif [ -f /run/TEST-82-SOFTREBOOT.touch2 ]; then
|
||||
# Restart the unit that is not supposed to survive
|
||||
systemd-run --collect --service-type=exec --unit=TEST-82-SOFTREBOOT-nosurvive.service sleep infinity
|
||||
|
||||
check_device_property 2
|
||||
trigger_uevent
|
||||
|
||||
# Now issue the soft reboot. We should be right back soon.
|
||||
touch /run/TEST-82-SOFTREBOOT.touch3
|
||||
systemctl --no-block soft-reboot
|
||||
@@ -176,6 +231,9 @@ elif [ -f /run/TEST-82-SOFTREBOOT.touch ]; then
|
||||
systemd-run --wait true
|
||||
done
|
||||
|
||||
check_device_property 1
|
||||
trigger_uevent
|
||||
|
||||
# Now issue the soft reboot. We should be right back soon. Given /run/nextroot exists, we should
|
||||
# automatically do a softreboot instead of normal reboot.
|
||||
touch /run/TEST-82-SOFTREBOOT.touch2
|
||||
@@ -266,6 +324,8 @@ EOF
|
||||
systemd-run --wait false || true
|
||||
done
|
||||
|
||||
trigger_uevent
|
||||
|
||||
# Now issue the soft reboot. We should be right back soon.
|
||||
touch /run/TEST-82-SOFTREBOOT.touch
|
||||
systemctl --no-block --check-inhibitors=yes soft-reboot
|
||||
|
||||
@@ -16,6 +16,14 @@ Before=sysinit.target
|
||||
Wants=systemd-udev-load-credentials.service
|
||||
ConditionPathIsReadWrite=/sys
|
||||
|
||||
# To avoid systemd-udevd being SIGKILLed during a soft reboot,
|
||||
# and causing queued uevents to be lost.
|
||||
# Note, typically soft-reboot.target will be never reached,
|
||||
# and systemd-soft-reboot.service will trigger soft-reboot.
|
||||
# Hence, this must be stopped before systemd-soft-reboot.service.
|
||||
Before=soft-reboot.target systemd-soft-reboot.service
|
||||
Conflicts=soft-reboot.target
|
||||
|
||||
[Service]
|
||||
CapabilityBoundingSet=~CAP_SYS_TIME CAP_WAKE_ALARM
|
||||
Delegate=pids
|
||||
|
||||
Reference in New Issue
Block a user