udev,sd-device: drop old database support (#40801)

Closes #40776.
This commit is contained in:
Yu Watanabe
2026-05-16 08:26:16 +09:00
committed by GitHub
5 changed files with 36 additions and 92 deletions
+2 -1
View File
@@ -6,6 +6,7 @@
#include "sd-forward.h"
#include "iterator.h"
#define OLDEST_UDEV_DATABASE_VERSION 1
#define LATEST_UDEV_DATABASE_VERSION 1
struct sd_device {
@@ -51,7 +52,7 @@ struct sd_device {
/* The database version indicates the supported features by the udev database.
* This is saved and parsed in V field.
*
* 0: None of the following features are supported (systemd version <= 246).
* 0: None of the following features are supported (systemd version <= 246), unsupported since v261.
* 1: The current tags (Q) and the database version (V) features are implemented (>= 247).
*/
unsigned database_version;
+1 -1
View File
@@ -912,7 +912,7 @@ int device_update_db(sd_device *device) {
fprintf(f, "Q:%s\n", ct); /* Current tag */
/* Always write the latest database version here, instead of the value stored in
* device->database_version, as which may be 0. */
* device->database_version. */
fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION) "\n", f);
}
+1 -21
View File
@@ -47,6 +47,7 @@ int device_new_aux(sd_device **ret) {
.devuid = UID_INVALID,
.devgid = GID_INVALID,
.action = _SD_DEVICE_ACTION_INVALID,
.database_version = OLDEST_UDEV_DATABASE_VERSION,
};
*ret = device;
@@ -1966,26 +1967,11 @@ _public_ const char* sd_device_get_tag_next(sd_device *device) {
return v;
}
static bool device_database_supports_current_tags(sd_device *device) {
assert(device);
(void) device_read_db(device);
/* The current tags (saved in Q field) feature is implemented in database version 1.
* If the database version is 0, then the tags (NOT current tags, saved in G field) are not
* sticky. Thus, we can safely bypass the operations for the current tags (Q) to tags (G). */
return device->database_version >= 1;
}
_public_ const char* sd_device_get_current_tag_first(sd_device *device) {
void *v;
assert_return(device, NULL);
if (!device_database_supports_current_tags(device))
return sd_device_get_tag_first(device);
(void) device_read_db(device);
device->current_tags_iterator_generation = device->tags_generation;
@@ -2000,9 +1986,6 @@ _public_ const char* sd_device_get_current_tag_next(sd_device *device) {
assert_return(device, NULL);
if (!device_database_supports_current_tags(device))
return sd_device_get_tag_next(device);
(void) device_read_db(device);
if (device->current_tags_iterator_generation != device->tags_generation)
@@ -2273,9 +2256,6 @@ _public_ int sd_device_has_current_tag(sd_device *device, const char *tag) {
assert_return(device, -EINVAL);
assert_return(tag, -EINVAL);
if (!device_database_supports_current_tags(device))
return sd_device_has_tag(device, tag);
(void) device_read_db(device);
return set_contains(device->current_tags, tag);
+22 -58
View File
@@ -79,84 +79,48 @@ static int node_create_symlink(sd_device *dev, const char *devnode, const char *
}
static int stack_directory_read_one(int dirfd, const char *id, char **devnode, int *priority) {
_cleanup_free_ char *buf = NULL;
int tmp_prio, r;
int r;
assert(dirfd >= 0);
assert(id);
assert(priority);
/* This reads priority and device node from the symlink under /run/udev/links (or udev database).
/* This reads priority and device node from the symlink under /run/udev/links/ directory.
* If 'devnode' is NULL, obtained priority is always set to '*priority'. If 'devnode' is non-NULL,
* this updates '*devnode' and '*priority'. */
* this updates '*devnode' and '*priority' if the obtained one has a higher priority. */
/* First, let's try to read the entry with the new format, which should replace the old format pretty
* quickly. */
_cleanup_free_ char *buf = NULL;
r = readlinkat_malloc(dirfd, id, &buf);
if (r >= 0) {
char *colon;
if (r < 0)
return r == -ENOENT ? -ENODEV : r;
/* With the new format, the devnode and priority can be obtained from symlink itself. */
char *colon = strchr(buf, ':');
if (!colon || colon == buf)
return -EINVAL;
colon = strchr(buf, ':');
if (!colon || colon == buf)
return -EINVAL;
*colon = '\0';
*colon = '\0';
/* Of course, this check is racy, but it is not necessary to be perfect. Even if the device
* node will be removed after this check, we will receive 'remove' uevent, and the invalid
* symlink will be removed during processing the event. The check is just for shortening the
* timespan that the symlink points to a non-existing device node. */
if (access(colon + 1, F_OK) < 0)
return -ENODEV;
/* Of course, this check is racy, but it is not necessary to be perfect. Even if the device
* node will be removed after this check, we will receive 'remove' uevent, and the invalid
* symlink will be removed during processing the event. The check is just for shortening the
* timespan that the symlink points to a non-existing device node. */
if (access(colon + 1, F_OK) < 0)
return -ENODEV;
r = safe_atoi(buf, &tmp_prio);
if (r < 0)
return r;
if (!devnode)
goto finalize;
int tmp_prio;
r = safe_atoi(buf, &tmp_prio);
if (r < 0)
return r;
if (devnode) {
if (*devnode && tmp_prio <= *priority)
return 0; /* Unchanged */
r = free_and_strdup(devnode, colon + 1);
if (r < 0)
return r;
}
} else if (r == -EINVAL) { /* Not a symlink ? try the old format */
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
const char *val;
/* Old format. The devnode and priority must be obtained from uevent and udev database. */
r = sd_device_new_from_device_id(&dev, id);
if (r < 0)
return r;
r = device_get_devlink_priority(dev, &tmp_prio);
if (r < 0)
return r;
if (!devnode)
goto finalize;
if (*devnode && tmp_prio <= *priority)
return 0; /* Unchanged */
r = sd_device_get_devname(dev, &val);
if (r < 0)
return r;
r = free_and_strdup(devnode, val);
if (r < 0)
return r;
} else
return r == -ENOENT ? -ENODEV : r;
finalize:
*priority = tmp_prio;
return 1; /* Updated */
}
+10 -11
View File
@@ -337,21 +337,20 @@ static int udev_watch_restore(Manager *manager) {
return log_warning_errno(errno, "Failed to open old watches directory '%s': %m", old);
FOREACH_DIRENT(de, dir, break) {
/* For backward compatibility, read symlink from watch handle to device ID. This is necessary
* when udevd is restarted after upgrading from v248 or older. The new format (ID -> wd) was
* introduced by e7f781e473f5119bf9246208a6de9f6b76a39c5d (v249). */
int wd;
if (safe_atoi(de->d_name, &wd) < 0)
continue; /* This should be ID -> wd symlink. Skipping. */
if (in_charset(de->d_name, DIGITS))
continue; /* This should be wd -> ID symlink. Skipping. */
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
r = device_new_from_watch_handle_at(&dev, dirfd(dir), wd);
r = sd_device_new_from_device_id(&dev, de->d_name);
if (r < 0) {
_cleanup_free_ char *wd_str = NULL;
if (ERRNO_IS_NEG_DEVICE_ABSENT(r) || DEBUG_LOGGING)
(void) readlinkat_malloc(dirfd(dir), de->d_name, &wd_str);
log_full_errno(ERRNO_IS_NEG_DEVICE_ABSENT(r) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to create sd_device object from saved watch handle '%i', ignoring: %m",
wd);
"Failed to create sd_device object from device ID '%s' for watch handle '%s', ignoring: %m",
de->d_name, strna(wd_str));
continue;
}