1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 06:25:37 +03:00

Merge pull request #23230 from yuwata/core-device-cleanups

core/device: several cleanups
This commit is contained in:
Yu Watanabe 2022-04-30 23:10:22 +09:00 committed by GitHub
commit dfd672f84b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 119 deletions

View File

@ -9,6 +9,7 @@
#include "bus-error.h"
#include "dbus-device.h"
#include "dbus-unit.h"
#include "device-private.h"
#include "device-util.h"
#include "device.h"
#include "log.h"
@ -24,9 +25,9 @@
#include "unit.h"
static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
[DEVICE_DEAD] = UNIT_INACTIVE,
[DEVICE_DEAD] = UNIT_INACTIVE,
[DEVICE_TENTATIVE] = UNIT_ACTIVATING,
[DEVICE_PLUGGED] = UNIT_ACTIVE,
[DEVICE_PLUGGED] = UNIT_ACTIVE,
};
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata);
@ -137,6 +138,7 @@ static int device_load(Unit *u) {
static void device_set_state(Device *d, DeviceState state) {
DeviceState old_state;
assert(d);
if (d->state != state)
@ -408,11 +410,9 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
if (r < 0)
return log_unit_error_errno(u, r, "Failed to add Wants= dependency: %m");
r = strv_push(&added, k);
r = strv_consume(&added, TAKE_PTR(k));
if (r < 0)
return log_oom();
k = NULL;
}
if (d->state != DEVICE_DEAD)
@ -440,20 +440,16 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
}
static bool device_is_bound_by_mounts(Device *d, sd_device *dev) {
const char *bound_by;
int r;
assert(d);
assert(dev);
if (sd_device_get_property_value(dev, "SYSTEMD_MOUNT_DEVICE_BOUND", &bound_by) >= 0) {
r = parse_boolean(bound_by);
if (r < 0)
log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_MOUNT_DEVICE_BOUND='%s' udev property, ignoring: %m", bound_by);
r = device_get_property_bool(dev, "SYSTEMD_MOUNT_DEVICE_BOUND");
if (r < 0 && r != -ENOENT)
log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_MOUNT_DEVICE_BOUND= udev property, ignoring: %m");
d->bind_mounts = r > 0;
} else
d->bind_mounts = false;
d->bind_mounts = r > 0;
return d->bind_mounts;
}
@ -476,10 +472,10 @@ static void device_upgrade_mount_deps(Unit *u) {
}
static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool main) {
_cleanup_(unit_freep) Unit *new_unit = NULL;
_cleanup_free_ char *e = NULL;
const char *sysfs = NULL;
Unit *u = NULL;
bool delete;
Unit *u;
int r;
assert(m);
@ -492,32 +488,12 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
}
r = unit_name_from_path(path, ".device", &e);
if (r < 0) {
/* Let's complain about overly long device names only at most once every 5s or so. This is
* something we should mention, since relevant devices are not manageable by systemd, but not
* flood the log about. */
static RateLimit rate_limit = {
.interval = 5 * USEC_PER_SEC,
.burst = 1,
};
/* If we cannot convert a device name to a unit name then let's ignore the device. So far,
* devices with such long names weren't really the kind you want to manage with systemd
* anyway, hence this shouldn't be a problem. */
if (r == -ENAMETOOLONG)
return log_struct_errno(
ratelimit_below(&rate_limit) ? LOG_WARNING : LOG_DEBUG, r,
"MESSAGE_ID=" SD_MESSAGE_DEVICE_PATH_NOT_SUITABLE_STR,
"DEVICE=%s", path,
LOG_MESSAGE("Device path '%s' too long to fit into unit name, ignoring device.", path));
if (r < 0)
return log_struct_errno(
ratelimit_below(&rate_limit) ? LOG_WARNING : LOG_DEBUG, r,
LOG_WARNING, r,
"MESSAGE_ID=" SD_MESSAGE_DEVICE_PATH_NOT_SUITABLE_STR,
"DEVICE=%s", path,
LOG_MESSAGE("Failed to generate valid unit name from device path '%s', ignoring device: %m", path));
}
u = manager_get_unit(m, e);
if (u) {
@ -537,19 +513,16 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
"Device %s appeared twice with different sysfs paths %s and %s, ignoring the latter.",
e, DEVICE(u)->sysfs, sysfs);
delete = false;
/* Let's remove all dependencies generated due to udev properties. We'll re-add whatever is configured
* now below. */
unit_remove_dependencies(u, UNIT_DEPENDENCY_UDEV);
} else {
delete = true;
r = unit_new_for_name(m, sizeof(Device), e, &u);
if (r < 0) {
log_device_error_errno(dev, r, "Failed to allocate device unit %s: %m", e);
goto fail;
}
} else {
r = unit_new_for_name(m, sizeof(Device), e, &new_unit);
if (r < 0)
return log_device_error_errno(dev, r, "Failed to allocate device unit %s: %m", e);
u = new_unit;
unit_add_to_load_queue(u);
}
@ -558,10 +531,8 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
* initialized. Hence initialize it if necessary. */
if (sysfs) {
r = device_set_sysfs(DEVICE(u), sysfs);
if (r < 0) {
log_unit_error_errno(u, r, "Failed to set sysfs path %s: %m", sysfs);
goto fail;
}
if (r < 0)
return log_unit_error_errno(u, r, "Failed to set sysfs path %s: %m", sysfs);
/* The additional systemd udev properties we only interpret for the main object */
if (main)
@ -577,13 +548,8 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
device_upgrade_mount_deps(u);
TAKE_PTR(new_unit);
return 0;
fail:
if (delete)
unit_free(u);
return r;
}
static void device_process_new(Manager *m, sd_device *dev) {
@ -592,6 +558,7 @@ static void device_process_new(Manager *m, sd_device *dev) {
int r;
assert(m);
assert(dev);
if (sd_device_get_syspath(dev, &sysfs) < 0)
return;
@ -738,8 +705,6 @@ static void device_update_found_by_name(Manager *m, const char *path, DeviceFoun
}
static bool device_is_ready(sd_device *dev) {
const char *ready;
assert(dev);
if (device_is_renaming(dev) > 0)
@ -749,10 +714,7 @@ static bool device_is_ready(sd_device *dev) {
if (sd_device_has_current_tag(dev, "systemd") <= 0)
return false;
if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0)
return true;
return parse_boolean(ready) != 0;
return device_get_property_bool(dev, "SYSTEMD_READY") != 0;
}
static Unit *device_following(Unit *u) {
@ -908,10 +870,13 @@ static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) {
}
static void device_remove_old_on_move(Manager *m, sd_device *dev) {
_cleanup_free_ char *syspath_old = NULL, *e = NULL;
_cleanup_free_ char *syspath_old = NULL;
const char *devpath_old;
int r;
assert(m);
assert(dev);
r = sd_device_get_property_value(dev, "DEVPATH_OLD", &devpath_old);
if (r < 0)
return (void) log_device_debug_errno(dev, r, "Failed to get DEVPATH_OLD= property on 'move' uevent, ignoring: %m");
@ -920,20 +885,15 @@ static void device_remove_old_on_move(Manager *m, sd_device *dev) {
if (!syspath_old)
return (void) log_oom();
r = unit_name_from_path(syspath_old, ".device", &e);
if (r < 0)
return (void) log_device_debug_errno(dev, r, "Failed to generate unit name from old device path, ignoring: %m");
device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_MASK);
}
static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
sd_device_action_t action;
Manager *m = userdata;
const char *sysfs;
int r;
assert(m);
assert(dev);
r = sd_device_get_syspath(dev, &sysfs);
@ -964,7 +924,7 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
/* 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_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_MASK);
} else if (device_is_ready(dev)) {
@ -986,64 +946,34 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
return 0;
}
static bool device_supported(void) {
static int read_only = -1;
/* If /sys is read-only we don't support device units, and any
* attempts to start one should fail immediately. */
if (read_only < 0)
read_only = path_is_read_only_fs("/sys");
return read_only <= 0;
}
static int validate_node(Manager *m, const char *node, sd_device **ret) {
struct stat st;
static int validate_node(const char *node, sd_device **ret) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
int r;
assert(m);
assert(node);
assert(ret);
/* Validates a device node that showed up in /proc/swaps or /proc/self/mountinfo if it makes sense for us to
* track. Note that this validator is fine within missing device nodes, but not with badly set up ones! */
if (!path_startswith(node, "/dev")) {
r = sd_device_new_from_devname(&dev, node);
if (r == -ENODEV) {
*ret = NULL;
return 0; /* bad! */
return 0; /* good! (though missing) */
}
if (r < 0)
return r; /* bad! */
if (stat(node, &st) < 0) {
if (errno != ENOENT)
return log_error_errno(errno, "Failed to stat() device node file %s: %m", node);
*ret = NULL;
return 1; /* good! (though missing) */
} else {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
r = sd_device_new_from_stat_rdev(&dev, &st);
if (r == -ENOENT) {
*ret = NULL;
return 1; /* good! (though missing) */
} else if (r == -ENOTTY) {
*ret = NULL;
return 0; /* bad! (not a device node but some other kind of file system node) */
} else if (r < 0)
return log_error_errno(r, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
*ret = TAKE_PTR(dev);
return 1; /* good! */
}
*ret = TAKE_PTR(dev);
return 1; /* good! */
}
void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
assert(m);
assert(node);
assert(!FLAGS_SET(mask, DEVICE_FOUND_UDEV));
if (!device_supported())
if (!udev_available())
return;
if (mask == 0)
@ -1064,10 +994,10 @@ void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFo
* under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
* everything is alright with the device node. */
if (validate_node(m, node, &dev) <= 0)
if (validate_node(node, &dev) < 0)
return; /* Don't create a device unit for this if the device node is borked. */
(void) device_setup_unit(m, dev, node, false);
(void) device_setup_unit(m, dev, node, false); /* 'dev' may be NULL. */
}
/* Update the device unit's state, should it exist */
@ -1113,7 +1043,7 @@ const UnitVTable device_vtable = {
.enumerate = device_enumerate,
.shutdown = device_shutdown,
.supported = device_supported,
.supported = udev_available,
.status_message_formats = {
.starting_stopping = {

View File

@ -17,6 +17,7 @@ static inline int device_new_from_watch_handle(sd_device **ret, int wd) {
return device_new_from_watch_handle_at(ret, -1, wd);
}
int device_get_property_bool(sd_device *device, const char *key);
int device_get_device_id(sd_device *device, const char **ret);
int device_get_devlink_priority(sd_device *device, int *ret);
int device_get_watch_handle(sd_device *device);

View File

@ -2007,6 +2007,20 @@ _public_ int sd_device_get_property_value(sd_device *device, const char *key, co
return 0;
}
int device_get_property_bool(sd_device *device, const char *key) {
const char *value;
int r;
assert(device);
assert(key);
r = sd_device_get_property_value(device, key, &value);
if (r < 0)
return r;
return parse_boolean(value);
}
_public_ int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret) {
const char *s;
sd_id128_t id;
@ -2296,7 +2310,7 @@ _public_ int sd_device_trigger_with_uuid(
_public_ int sd_device_open(sd_device *device, int flags) {
_cleanup_close_ int fd = -1, fd2 = -1;
const char *devname, *subsystem = NULL, *val = NULL;
const char *devname, *subsystem = NULL;
uint64_t q, diskseq = 0;
struct stat st;
dev_t devnum;
@ -2338,11 +2352,10 @@ _public_ int sd_device_open(sd_device *device, int flags) {
if (FLAGS_SET(flags, O_PATH))
return TAKE_FD(fd);
r = sd_device_get_property_value(device, "ID_IGNORE_DISKSEQ", &val);
r = device_get_property_bool(device, "ID_IGNORE_DISKSEQ");
if (r < 0 && r != -ENOENT)
return r;
if (!val || parse_boolean(val) <= 0) {
if (r <= 0) {
r = sd_device_get_diskseq(device, &diskseq);
if (r < 0 && r != -ENOENT)
return r;