diff --git a/src/core/device.c b/src/core/device.c index fcde8a420e..4f9bf24db8 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -31,7 +31,6 @@ static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = { }; static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata); -static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask); static void device_unset_sysfs(Device *d) { Hashmap *devices; @@ -116,6 +115,7 @@ static void device_done(Unit *u) { device_unset_sysfs(d); d->wants_property = strv_free(d->wants_property); + d->path = mfree(d->path); } static int device_load(Unit *u) { @@ -156,6 +156,85 @@ static void device_set_state(Device *d, DeviceState state) { unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], 0); } +static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) { + assert(d); + + /* Didn't exist before, but does now? if so, generate a new invocation ID for it */ + if (previous == DEVICE_NOT_FOUND && now != DEVICE_NOT_FOUND) + (void) unit_acquire_invocation_id(UNIT(d)); + + if (FLAGS_SET(now, DEVICE_FOUND_UDEV)) + /* When the device is known to udev we consider it plugged. */ + device_set_state(d, DEVICE_PLUGGED); + else if (now != DEVICE_NOT_FOUND && !FLAGS_SET(previous, DEVICE_FOUND_UDEV)) + /* If the device has not been seen by udev yet, but is now referenced by the kernel, then we assume the + * kernel knows it now, and udev might soon too. */ + device_set_state(d, DEVICE_TENTATIVE); + else + /* If nobody sees the device, or if the device was previously seen by udev and now is only referenced + * from the kernel, then we consider the device is gone, the kernel just hasn't noticed it yet. */ + device_set_state(d, DEVICE_DEAD); +} + +static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) { + assert(d); + + if (MANAGER_IS_RUNNING(UNIT(d)->manager)) { + DeviceFound n, previous; + + /* When we are already running, then apply the new mask right-away, and trigger state changes + * right-away */ + + n = (d->found & ~mask) | (found & mask); + if (n == d->found) + return; + + previous = d->found; + d->found = n; + + device_found_changed(d, previous, n); + } else + /* We aren't running yet, let's apply the new mask to the shadow variable instead, which we'll apply as + * soon as we catch-up with the state. */ + d->enumerated_found = (d->enumerated_found & ~mask) | (found & mask); +} + +static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFound found, DeviceFound mask) { + Device *l; + + assert(m); + assert(sysfs); + + if (mask == 0) + return; + + l = hashmap_get(m->devices_by_sysfs, sysfs); + LIST_FOREACH(same_sysfs, d, l) + device_update_found_one(d, found, mask); +} + +static void device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) { + _cleanup_free_ char *e = NULL; + Unit *u; + int r; + + assert(m); + assert(path); + + if (mask == 0) + return; + + r = unit_name_from_path(path, ".device", &e); + if (r < 0) + return (void) log_debug_errno(r, "Failed to generate unit name from device path, ignoring: %m"); + + u = manager_get_unit(m, e); + if (!u) + return; + + device_update_found_one(DEVICE(u), found, mask); +} + static int device_coldplug(Unit *u) { Device *d = DEVICE(u); @@ -191,9 +270,8 @@ static int device_coldplug(Unit *u) { * 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 initramfs and the main system are often different. If the deserialized - * state is DEVICE_PLUGGED, we need to downgrade it to DEVICE_TENTATIVE (or DEVICE_DEAD if nobody - * sees the device). Unlike the other starting mode, Manager.honor_device_enumeration == false - * (maybe, it is better to rename the flag) when device_coldplug() and device_catchup() are called. + * 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. * @@ -201,7 +279,7 @@ static int device_coldplug(Unit *u) { * Of course, deserialized parameters may be outdated, but the unit state can be adjusted later by * device_catchup() or uevents. */ - if (!m->honor_device_enumeration && !MANAGER_IS_USER(m) && + if (MANAGER_IS_SWITCHING_ROOT(m) && !FLAGS_SET(d->enumerated_found, DEVICE_FOUND_UDEV)) { found &= ~DEVICE_FOUND_UDEV; /* ignore DEVICE_FOUND_UDEV bit */ if (state == DEVICE_PLUGGED) @@ -294,6 +372,9 @@ static int device_serialize(Unit *u, FILE *f, FDSet *fds) { assert(f); assert(fds); + if (d->path) + (void) serialize_item(f, "path", d->path); + (void) serialize_item(f, "state", device_state_to_string(d->state)); if (device_found_to_string_many(d->found, &s) >= 0) @@ -312,7 +393,14 @@ static int device_deserialize_item(Unit *u, const char *key, const char *value, assert(value); assert(fds); - if (streq(key, "state")) { + if (streq(key, "path")) { + if (!d->path) { + d->path = strdup(value); + if (!d->path) + log_oom_debug(); + } + + } else if (streq(key, "state")) { DeviceState state; state = device_state_from_string(value); @@ -342,9 +430,11 @@ static void device_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sDevice State: %s\n" + "%sDevice Path: %s\n" "%sSysfs Path: %s\n" "%sFound: %s\n", prefix, device_state_to_string(d->state), + prefix, strna(d->path), prefix, strna(d->sysfs), prefix, strna(s)); @@ -542,16 +632,9 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool * dependency on the mount unit which was added during the loading of the later. When the device is * plugged the sysfs might not be initialized yet, as we serialize the device's state but do not * serialize the sysfs path across reloads/reexecs. Hence, when coming back from a reload/restart we - * might have the state valid, but not the sysfs path. Hence, let's filter out conflicting devices, but - * let's accept devices in any state with no sysfs path set. */ - - if (DEVICE(u)->state == DEVICE_PLUGGED && - DEVICE(u)->sysfs && - sysfs && - !path_equal(DEVICE(u)->sysfs, sysfs)) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EEXIST), - "Device %s appeared twice with different sysfs paths %s and %s, ignoring the latter.", - e, DEVICE(u)->sysfs, sysfs); + * might have the state valid, but not the sysfs path. Also, there is another possibility; when multiple + * devices have the same devlink (e.g. /dev/disk/by-uuid/xxxx), adding/updating/removing one of the + * device causes syspath change. Hence, let's always update sysfs path.*/ /* Let's remove all dependencies generated due to udev properties. We'll re-add whatever is configured * now below. */ @@ -567,6 +650,12 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool unit_add_to_load_queue(u); } + if (!DEVICE(u)->path) { + DEVICE(u)->path = strdup(path); + if (!DEVICE(u)->path) + return log_oom(); + } + /* If this was created via some dependency and has not actually been seen yet ->sysfs will not be * initialized. Hence initialize it if necessary. */ if (sysfs) { @@ -592,158 +681,6 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool return 0; } -static void device_process_new(Manager *m, sd_device *dev, const char *sysfs) { - const char *dn, *alias; - dev_t devnum; - int r; - - assert(m); - assert(dev); - assert(sysfs); - - /* Add the main unit named after the sysfs path. If this one fails, don't bother with the rest, as - * this one shall be the main device unit the others just follow. (Compare with how - * device_following() is implemented, see below, which looks for the sysfs device.) */ - if (device_setup_unit(m, dev, sysfs, true) < 0) - return; - - /* Add an additional unit for the device node */ - if (sd_device_get_devname(dev, &dn) >= 0) - (void) device_setup_unit(m, dev, dn, false); - - /* Add additional units for all symlinks */ - if (sd_device_get_devnum(dev, &devnum) >= 0) { - const char *p; - - FOREACH_DEVICE_DEVLINK(dev, p) { - struct stat st; - - if (PATH_STARTSWITH_SET(p, "/dev/block/", "/dev/char/")) - continue; - - /* Verify that the symlink in the FS actually belongs to this device. This is useful - * to deal with conflicting devices, e.g. when two disks want the same - * /dev/disk/by-label/xxx link because they have the same label. We want to make sure - * that the same device that won the symlink wins in systemd, so we check the device - * node major/minor */ - if (stat(p, &st) >= 0 && - ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) || - st.st_rdev != devnum)) { - log_device_debug(dev, "Skipping device unit creation for symlink %s not owned by device", p); - continue; - } - - (void) device_setup_unit(m, dev, p, false); - } - } - - /* Add additional units for all explicitly configured aliases */ - r = sd_device_get_property_value(dev, "SYSTEMD_ALIAS", &alias); - if (r < 0) { - if (r != -ENOENT) - log_device_error_errno(dev, r, "Failed to get SYSTEMD_ALIAS property, ignoring: %m"); - return; - } - - for (;;) { - _cleanup_free_ char *word = NULL; - - r = extract_first_word(&alias, &word, NULL, EXTRACT_UNQUOTE); - if (r == 0) - break; - if (r == -ENOMEM) - return (void) log_oom(); - if (r < 0) - return (void) log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property, ignoring: %m"); - - if (!path_is_absolute(word)) - log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word); - else if (!path_is_normalized(word)) - log_device_warning(dev, "SYSTEMD_ALIAS is not a normalized path, ignoring: %s", word); - else - (void) device_setup_unit(m, dev, word, false); - } -} - -static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) { - assert(d); - - /* Didn't exist before, but does now? if so, generate a new invocation ID for it */ - if (previous == DEVICE_NOT_FOUND && now != DEVICE_NOT_FOUND) - (void) unit_acquire_invocation_id(UNIT(d)); - - if (FLAGS_SET(now, DEVICE_FOUND_UDEV)) - /* When the device is known to udev we consider it plugged. */ - device_set_state(d, DEVICE_PLUGGED); - else if (now != DEVICE_NOT_FOUND && !FLAGS_SET(previous, DEVICE_FOUND_UDEV)) - /* If the device has not been seen by udev yet, but is now referenced by the kernel, then we assume the - * kernel knows it now, and udev might soon too. */ - device_set_state(d, DEVICE_TENTATIVE); - else - /* If nobody sees the device, or if the device was previously seen by udev and now is only referenced - * from the kernel, then we consider the device is gone, the kernel just hasn't noticed it yet. */ - device_set_state(d, DEVICE_DEAD); -} - -static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) { - assert(d); - - if (MANAGER_IS_RUNNING(UNIT(d)->manager)) { - DeviceFound n, previous; - - /* When we are already running, then apply the new mask right-away, and trigger state changes - * right-away */ - - n = (d->found & ~mask) | (found & mask); - if (n == d->found) - return; - - previous = d->found; - d->found = n; - - device_found_changed(d, previous, n); - } else - /* We aren't running yet, let's apply the new mask to the shadow variable instead, which we'll apply as - * soon as we catch-up with the state. */ - d->enumerated_found = (d->enumerated_found & ~mask) | (found & mask); -} - -static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFound found, DeviceFound mask) { - Device *l; - - assert(m); - assert(sysfs); - - if (mask == 0) - return; - - l = hashmap_get(m->devices_by_sysfs, sysfs); - LIST_FOREACH(same_sysfs, d, l) - device_update_found_one(d, found, mask); -} - -static void device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) { - _cleanup_free_ char *e = NULL; - Unit *u; - int r; - - assert(m); - assert(path); - - if (mask == 0) - return; - - r = unit_name_from_path(path, ".device", &e); - if (r < 0) - return (void) log_debug_errno(r, "Failed to generate unit name from device path, ignoring: %m"); - - u = manager_get_unit(m, e); - if (!u) - return; - - device_update_found_one(DEVICE(u), found, mask); -} - static bool device_is_ready(sd_device *dev) { int r; @@ -775,6 +712,155 @@ static bool device_is_ready(sd_device *dev) { return r != 0; } +static int device_setup_devlink_unit_one(Manager *m, const char *devlink, sd_device **ret) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + int r; + + assert(m); + assert(devlink); + + if (sd_device_new_from_devname(&dev, devlink) < 0 || !device_is_ready(dev)) { + /* the devlink is already removed or not ready */ + device_update_found_by_name(m, devlink, 0, DEVICE_FOUND_UDEV); + *ret = NULL; + return 0; /* not ready */ + } + + r = device_setup_unit(m, dev, devlink, /* main = */ false); + if (r < 0) + return log_device_warning_errno(dev, r, "Failed to setup unit for '%s': %m", devlink); + + *ret = TAKE_PTR(dev); + return 1; /* ready */ +} + +static int device_setup_devlink_units(Manager *m, sd_device *dev, char ***ret_ready_devlinks) { + _cleanup_strv_free_ char **ready_devlinks = NULL; + const char *devlink, *syspath; + int r; + + assert(m); + assert(dev); + assert(ret_ready_devlinks); + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + FOREACH_DEVICE_DEVLINK(dev, devlink) { + _cleanup_(sd_device_unrefp) sd_device *assigned = NULL; + const char *s; + + if (PATH_STARTSWITH_SET(devlink, "/dev/block/", "/dev/char/")) + continue; + + if (device_setup_devlink_unit_one(m, devlink, &assigned) <= 0) + continue; + + if (sd_device_get_syspath(assigned, &s) < 0) + continue; + + if (path_equal(s, syspath)) + continue; + + r = strv_extend(&ready_devlinks, devlink); + if (r < 0) + return -ENOMEM; + } + + *ret_ready_devlinks = TAKE_PTR(ready_devlinks); + return 0; +} + +static int device_setup_devlink_units_on_remove(Manager *m, sd_device *dev, char ***ret_ready_devlinks) { + _cleanup_strv_free_ char **ready_devlinks = NULL; + const char *syspath; + Device *l; + int r; + + assert(m); + assert(dev); + assert(ret_ready_devlinks); + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + l = hashmap_get(m->devices_by_sysfs, syspath); + LIST_FOREACH(same_sysfs, d, l) { + _cleanup_(sd_device_unrefp) sd_device *assigned = NULL; + const char *s; + + if (!d->path) + continue; + + if (!path_startswith(d->path, "/dev/")) + continue; + + if (device_setup_devlink_unit_one(m, d->path, &assigned) <= 0) + continue; + + if (sd_device_get_syspath(assigned, &s) < 0) + continue; + + if (path_equal(s, syspath)) + continue; + + r = strv_extend(&ready_devlinks, d->path); + if (r < 0) + return -ENOMEM; + } + + *ret_ready_devlinks = TAKE_PTR(ready_devlinks); + return 0; +} + +static void device_process_new(Manager *m, sd_device *dev, const char *sysfs) { + const char *dn, *alias; + int r; + + assert(m); + assert(dev); + assert(sysfs); + + /* Add the main unit named after the sysfs path. If this one fails, don't bother with the rest, as + * this one shall be the main device unit the others just follow. (Compare with how + * device_following() is implemented, see below, which looks for the sysfs device.) */ + if (device_setup_unit(m, dev, sysfs, /* main = */ true) < 0) + return; + + /* Add an additional unit for the device node */ + if (sd_device_get_devname(dev, &dn) >= 0) + (void) device_setup_unit(m, dev, dn, /* main = */ false); + + /* Add additional units for all explicitly configured aliases */ + r = sd_device_get_property_value(dev, "SYSTEMD_ALIAS", &alias); + if (r < 0) { + if (r != -ENOENT) + log_device_error_errno(dev, r, "Failed to get SYSTEMD_ALIAS property, ignoring: %m"); + return; + } + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&alias, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return (void) log_oom(); + if (r < 0) + return (void) log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property, ignoring: %m"); + + if (!path_is_absolute(word)) + log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word); + else if (!path_is_normalized(word)) + log_device_warning(dev, "SYSTEMD_ALIAS is not a normalized path, ignoring: %s", word); + else + (void) device_setup_unit(m, dev, word, /* main = */ false); + } +} + static Unit *device_following(Unit *u) { Device *d = DEVICE(u); Device *first = NULL; @@ -890,10 +976,9 @@ static void device_enumerate(Manager *m) { } FOREACH_DEVICE(e, dev) { + _cleanup_strv_free_ char **ready_devlinks = NULL; const char *sysfs; - - if (!device_is_ready(dev)) - continue; + bool ready; r = sd_device_get_syspath(dev, &sysfs); if (r < 0) { @@ -901,8 +986,18 @@ static void device_enumerate(Manager *m) { continue; } - device_process_new(m, dev, sysfs); - device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); + ready = device_is_ready(dev); + if (ready) + device_process_new(m, dev, sysfs); + + /* Add additional units for all symlinks */ + (void) device_setup_devlink_units(m, dev, &ready_devlinks); + + if (ready) + device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); + + STRV_FOREACH(devlink, ready_devlinks) + device_update_found_by_name(m, *devlink, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); } return; @@ -925,10 +1020,34 @@ static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) { r = manager_propagate_reload(m, UNIT(d), JOB_REPLACE, NULL); if (r < 0) - log_warning_errno(r, "Failed to propagate reload, ignoring: %m"); + log_unit_warning_errno(UNIT(d), r, "Failed to propagate reload, ignoring: %m"); } } +static void device_propagate_reload_by_name(Manager *m, const char *path) { + _cleanup_free_ char *e = NULL; + Unit *u; + int r; + + assert(m); + assert(path); + + r = unit_name_from_path(path, ".device", &e); + if (r < 0) + return (void) log_debug_errno(r, "Failed to generate unit name from device path, ignoring: %m"); + + u = manager_get_unit(m, e); + if (!u) + return; + + if (DEVICE(u)->state == DEVICE_DEAD) + return; + + r = manager_propagate_reload(m, u, JOB_REPLACE, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to propagate reload, ignoring: %m"); +} + static void device_remove_old_on_move(Manager *m, sd_device *dev) { _cleanup_free_ char *syspath_old = NULL; const char *devpath_old; @@ -949,9 +1068,11 @@ static void device_remove_old_on_move(Manager *m, sd_device *dev) { } static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) { + _cleanup_strv_free_ char **ready_devlinks = NULL; Manager *m = ASSERT_PTR(userdata); sd_device_action_t action; const char *sysfs; + bool ready; int r; assert(dev); @@ -970,9 +1091,6 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * return 0; } - if (!IN_SET(action, SD_DEVICE_ADD, SD_DEVICE_REMOVE, SD_DEVICE_MOVE)) - device_propagate_reload_by_sysfs(m, sysfs); - if (action == SD_DEVICE_MOVE) device_remove_old_on_move(m, dev); @@ -984,27 +1102,50 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * if (r < 0) log_device_warning_errno(dev, r, "Failed to process swap device remove event, ignoring: %m"); - /* If we get notified that a device was removed by udev, then it's completely gone, hence - * unset all found bits */ - device_update_found_by_sysfs(m, sysfs, DEVICE_NOT_FOUND, DEVICE_FOUND_MASK); + ready = false; - } else if (device_is_ready(dev)) { + (void) device_setup_devlink_units_on_remove(m, dev, &ready_devlinks); - device_process_new(m, dev, sysfs); + } else { + ready = device_is_ready(dev); - r = swap_process_device_new(m, dev); - if (r < 0) - log_device_warning_errno(dev, r, "Failed to process swap device new event, ignoring: %m"); + if (ready) { + device_process_new(m, dev, sysfs); + r = swap_process_device_new(m, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to process swap device new event, ignoring: %m"); + } + + /* Add additional units for all symlinks */ + (void) device_setup_devlink_units(m, dev, &ready_devlinks); + } + + if (!IN_SET(action, SD_DEVICE_ADD, SD_DEVICE_REMOVE, SD_DEVICE_MOVE)) { + device_propagate_reload_by_sysfs(m, sysfs); + + STRV_FOREACH(devlink, ready_devlinks) + device_propagate_reload_by_name(m, *devlink); + } + + if (ready || !strv_isempty(ready_devlinks)) manager_dispatch_load_queue(m); + if (action == SD_DEVICE_REMOVE) + /* If we get notified that a device was removed by udev, then it's completely gone, hence + * unset all found bits */ + device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_MASK); + else if (ready) /* The device is found now, set the udev found bit */ device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); - } else + else /* The device is nominally around, but not ready for us. Hence unset the udev bit, but leave * the rest around. */ device_update_found_by_sysfs(m, sysfs, DEVICE_NOT_FOUND, DEVICE_FOUND_UDEV); + STRV_FOREACH(devlink, ready_devlinks) + device_update_found_by_name(m, *devlink, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); + return 0; } @@ -1047,7 +1188,7 @@ void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFo return; } - (void) device_setup_unit(m, dev, node, false); /* 'dev' may be NULL. */ + (void) device_setup_unit(m, dev, node, /* main = */ false); /* 'dev' may be NULL. */ } /* Update the device unit's state, should it exist */ diff --git a/src/core/device.h b/src/core/device.h index dfe8a13aff..7584bc70c4 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -21,6 +21,7 @@ struct Device { Unit meta; char *sysfs; + char *path; /* syspath, device node, alias, or devlink */ /* In order to be able to distinguish dependencies on different device nodes we might end up creating multiple * devices for the same sysfs path. We chain them up here. */ diff --git a/src/core/main.c b/src/core/main.c index fbbfd71ac8..9ad3983b20 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1966,6 +1966,8 @@ static int invoke_main_loop( return objective; case MANAGER_SWITCH_ROOT: + manager_set_switching_root(m, true); + if (!m->switch_root_init) { r = prepare_reexecute(m, &arg_serialization, ret_fds, true); if (r < 0) { @@ -2943,6 +2945,7 @@ int main(int argc, char *argv[]) { set_manager_defaults(m); set_manager_settings(m); manager_set_first_boot(m, first_boot); + manager_set_switching_root(m, arg_switched_root); /* Remember whether we should queue the default job */ queue_default_job = !arg_serialization || arg_switched_root; diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index a91c8268d5..914bd92e36 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -103,9 +103,6 @@ int manager_serialize( (void) serialize_bool(f, "taint-logged", m->taint_logged); (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs); - /* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */ - (void) serialize_bool(f, "honor-device-enumeration", !switching_root); - if (m->show_status_overridden != _SHOW_STATUS_INVALID) (void) serialize_item(f, "show-status-overridden", show_status_to_string(m->show_status_overridden)); @@ -399,15 +396,6 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { else m->service_watchdogs = b; - } else if ((val = startswith(l, "honor-device-enumeration="))) { - int b; - - b = parse_boolean(val); - if (b < 0) - log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val); - else - m->honor_device_enumeration = b; - } else if ((val = startswith(l, "show-status-overridden="))) { ShowStatus s; @@ -544,7 +532,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { if (q < _MANAGER_TIMESTAMP_MAX) /* found it */ (void) deserialize_dual_timestamp(val, m->timestamps + q); - else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */ + else if (!STARTSWITH_SET(l, "kdbus-fd=", "honor-device-enumeration=")) /* ignore deprecated values */ log_notice("Unknown serialization item '%s', ignoring.", l); } } diff --git a/src/core/manager.c b/src/core/manager.c index 45f6dccf4a..f153641510 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -807,6 +807,10 @@ static int manager_find_credentials_dirs(Manager *m) { return 0; } +void manager_set_switching_root(Manager *m, bool switching_root) { + m->switching_root = MANAGER_IS_SYSTEM(m) && switching_root; +} + int manager_new(LookupScope scope, ManagerTestRunFlags test_run_flags, Manager **_m) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -1760,8 +1764,6 @@ static void manager_ready(Manager *m) { (void) touch_file("/run/systemd/systemd-units-load", false, m->timestamps[MANAGER_TIMESTAMP_UNITS_LOAD].realtime ?: now(CLOCK_REALTIME), UID_INVALID, GID_INVALID, 0444); - - m->honor_device_enumeration = true; } Manager* manager_reloading_start(Manager *m) { @@ -1872,6 +1874,8 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo manager_ready(m); + manager_set_switching_root(m, false); + return 0; } @@ -3418,11 +3422,6 @@ int manager_reload(Manager *m) { assert(m->n_reloading > 0); m->n_reloading--; - /* On manager reloading, device tag data should exists, thus, we should honor the results of device - * enumeration. The flag should be always set correctly by the serialized data, but it may fail. So, - * let's always set the flag here for safety. */ - m->honor_device_enumeration = true; - manager_ready(m); m->send_reloading_done = true; diff --git a/src/core/manager.h b/src/core/manager.h index 63cff7989d..e4603daff2 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -406,6 +406,9 @@ struct Manager { char *switch_root; char *switch_root_init; + /* This is true before and after switching root. */ + bool switching_root; + /* This maps all possible path prefixes to the units needing * them. It's a hashmap with a path string as key and a Set as * value where Unit objects are contained. */ @@ -446,8 +449,6 @@ struct Manager { unsigned sigchldgen; unsigned notifygen; - bool honor_device_enumeration; - VarlinkServer *varlink_server; /* When we're a system manager, this object manages the subscription from systemd-oomd to PID1 that's * used to report changes in ManagedOOM settings (systemd server - oomd client). When @@ -476,6 +477,8 @@ static inline usec_t manager_default_timeout_abort_usec(Manager *m) { /* The objective is set to OK as soon as we enter the main loop, and set otherwise as soon as we are done with it */ #define MANAGER_IS_RUNNING(m) ((m)->objective == MANAGER_OK) +#define MANAGER_IS_SWITCHING_ROOT(m) ((m)->switching_root) + #define MANAGER_IS_TEST_RUN(m) ((m)->test_run_flags != 0) int manager_new(LookupScope scope, ManagerTestRunFlags test_run_flags, Manager **m); @@ -541,6 +544,7 @@ void manager_set_show_status(Manager *m, ShowStatus mode, const char *reason); void manager_override_show_status(Manager *m, ShowStatus mode, const char *reason); void manager_set_first_boot(Manager *m, bool b); +void manager_set_switching_root(Manager *m, bool switching_root); void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5);