From: Yu Watanabe Date: Mon, 27 Jun 2022 21:20:19 +0000 (+0900) Subject: core/device: start units specified in SYSTEMD_WANTS if it is not running X-Git-Tag: v252-rc1~479^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=033fe6506af5881db77c5ec1bb1f135bd6093406;p=thirdparty%2Fsystemd.git core/device: start units specified in SYSTEMD_WANTS if it is not running Otherwise, e.g. --- KERNEL=="foo", ACTION!="remove", ENV{SYSTEMD_WANTS}+="test.service" --- then the service will not triggered on CHANGE uevents for the device even if the service is already stopped. --- diff --git a/src/core/device.c b/src/core/device.c index fcde8a420e6..90d6324d962 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -457,18 +457,24 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) { if (d->state != DEVICE_DEAD) /* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not * synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device - * changes while the device unit is already up, let's manually trigger any new units listed in it not - * seen before. This typically happens during the boot-time switch root transition, as udev devices - * will generally already be up in the initrd, but SYSTEMD_WANTS properties get then added through udev - * rules only available on the host system, and thus only when the initial udev coldplug trigger runs. + * changes while the device unit is already up, let's skip to trigger units that were already listed + * and are active, and start units otherwise. This typically happens during the boot-time switch root + * transition, as udev devices will generally already be up in the initrd, but SYSTEMD_WANTS properties + * get then added through udev rules only available on the host system, and thus only when the initial + * udev coldplug trigger runs. * * We do this only if the device has been up already when we parse this, as otherwise the usual * dependency logic that is run from the dead → plugged transition will trigger these deps. */ STRV_FOREACH(i, added) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */ - continue; + if (strv_contains(d->wants_property, *i)) { + Unit *v; + + v = manager_get_unit(u->manager, *i); + if (v && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(v))) + continue; /* The unit was already listed and is running. */ + } r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, NULL, &error, NULL); if (r < 0)