From 10b3ce781bbad6a8636a8cc442065c93595bf63a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Dec 08 2022 20:29:56 +0000 Subject: core/device: update comment (cherry picked from commit 54a4d71509c0f3401aa576346754a0781795214a) --- diff --git a/src/core/device.c b/src/core/device.c index 224fc90..c79fd08 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -267,7 +267,7 @@ static int device_coldplug(Unit *u) { * 1. MANAGER_IS_RUNNING() == false * 2. enumerate devices: manager_enumerate() -> device_enumerate() * Device.enumerated_found is set. - * 3. deserialize devices: manager_deserialize() -> device_deserialize() + * 3. deserialize devices: manager_deserialize() -> device_deserialize_item() * Device.deserialize_state and Device.deserialized_found are set. * 4. coldplug devices: manager_coldplug() -> device_coldplug() * deserialized properties are copied to the main properties. @@ -282,23 +282,28 @@ static int device_coldplug(Unit *u) { * * - On switch-root, the udev database may be cleared, except for devices with sticky bit, i.e. * OPTIONS="db_persist". Hence, almost no devices are enumerated in the step 2. However, in - * general, we have several serialized devices. So, DEVICE_FOUND_UDEV bit in the deserialized_found - * must be ignored, as udev rules in initrd and the main system are often different. If the - * deserialized state is DEVICE_PLUGGED, we need to downgrade it to DEVICE_TENTATIVE. Unlike the - * other starting mode, MANAGER_IS_SWITCHING_ROOT() is true when device_coldplug() and - * device_catchup() are called. Hence, let's conditionalize the operations by using the - * flag. After switch-root, systemd-udevd will (re-)process all devices, and the Device.found and - * Device.state will be adjusted. + * general, we have several serialized devices. So, DEVICE_FOUND_UDEV bit in the + * Device.deserialized_found must be ignored, as udev rules in initrd and the main system are often + * different. If the deserialized state is DEVICE_PLUGGED, we need to downgrade it to + * DEVICE_TENTATIVE. Unlike the other starting mode, MANAGER_IS_SWITCHING_ROOT() is true when + * device_coldplug() and device_catchup() are called. Hence, let's conditionalize the operations by + * using the flag. After switch-root, systemd-udevd will (re-)process all devices, and the + * Device.found and Device.state will be adjusted. * - * - On reload or reexecute, we can trust enumerated_found, deserialized_found, and deserialized_state. - * Of course, deserialized parameters may be outdated, but the unit state can be adjusted later by - * device_catchup() or uevents. */ + * - On reload or reexecute, we can trust Device.enumerated_found, Device.deserialized_found, and + * Device.deserialized_state. Of course, deserialized parameters may be outdated, but the unit + * state can be adjusted later by device_catchup() or uevents. */ if (MANAGER_IS_SWITCHING_ROOT(m) && !FLAGS_SET(d->enumerated_found, DEVICE_FOUND_UDEV)) { - found &= ~DEVICE_FOUND_UDEV; /* ignore DEVICE_FOUND_UDEV bit */ + + /* The device has not been enumerated. On switching-root, such situation is natural. See the + * above comment. To prevent problematic state transition active → dead → active, let's + * drop the DEVICE_FOUND_UDEV flag and downgrade state to DEVICE_TENTATIVE(activating). See + * issue #12953 and #23208. */ + found &= ~DEVICE_FOUND_UDEV; if (state == DEVICE_PLUGGED) - state = DEVICE_TENTATIVE; /* downgrade state */ + state = DEVICE_TENTATIVE; } if (d->found == found && d->state == state)