]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udevadm-info: handle missing data db cleanup 42958/head
authordongshengyuan <545258830@qq.com>
Fri, 10 Jul 2026 08:09:34 +0000 (16:09 +0800)
committerdongshengyuan <545258830@qq.com>
Fri, 10 Jul 2026 08:09:34 +0000 (16:09 +0800)
udevadm info --cleanup-db cleaned links and tags by comparing them
against /run/udev/data, but asserted when that data directory was
missing.

Treat a missing data directory as an empty database, so stale link
and tag entries can be removed without aborting.

Add a database test that runs cleanup-db with links and tags present
but no data directory.

Reproducer:

$ sudo unshare --mount --propagation private sh -c '
mount -t tmpfs tmpfs /run/udev
mkdir -p /run/udev/links/foo
udevadm info --cleanup-db
'
Assertion 'datadir' failed at src/udev/udevadm-info.c:676, function cleanup_dirs_after_db_cleanup(). Aborting.
Aborted (core dumped)

The command should handle a missing /run/udev/data directory instead
of aborting.

src/udev/udevadm-info.c
test/units/TEST-17-UDEV.database.sh

index f2944b02f3197afcb9116c2b43f334b9d4b66fc4..78c9520017c0eea533721f14fa7631df5a8665cf 100644 (file)
@@ -655,16 +655,16 @@ static void cleanup_dir(DIR *dir, mode_t mask, int depth) {
  * entries for devices in /run/udev/data (such as "b8:16"), and removes
  * all files except those that haven't been deleted in /run/udev/data
  * (i.e. they were skipped during db cleanup because of the db_persist flag).
+ * If the database directory does not exist, all entries are considered stale.
  */
 static void cleanup_dir_after_db_cleanup(DIR *dir, DIR *datadir) {
         assert(dir);
-        assert(datadir);
 
         FOREACH_DIRENT_ALL(dent, dir, break) {
                 if (dot_or_dot_dot(dent->d_name))
                         continue;
 
-                if (faccessat(dirfd(datadir), dent->d_name, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+                if (datadir && faccessat(dirfd(datadir), dent->d_name, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
                         /* The corresponding udev database file still exists.
                          * Assuming the persistent flag is set for the database. */
                         continue;
@@ -675,7 +675,6 @@ static void cleanup_dir_after_db_cleanup(DIR *dir, DIR *datadir) {
 
 static void cleanup_dirs_after_db_cleanup(DIR *dir, DIR *datadir) {
         assert(dir);
-        assert(datadir);
 
         FOREACH_DIRENT_ALL(dent, dir, break) {
                 struct stat stats;
index 56a79a665b0e727787d0cf67b15e412b6e44b83f..ed50daa5ad396821354a986951ad12cc397d8f36 100755 (executable)
@@ -15,4 +15,15 @@ udevadm wait --timeout=10 --removed --settle "/sys/class/net/$IFNAME"
 # CHeck if the database file is removed.
 [[ ! -e "/run/udev/data/n$IFINDEX" ]]
 
+unshare --mount --propagation private bash -eux <<'EOF'
+mount -t tmpfs tmpfs /run/udev
+mkdir -p /run/udev/links/test /run/udev/tags/test
+touch /run/udev/links/test/stale /run/udev/tags/test/stale
+
+udevadm info --cleanup-db
+
+[[ ! -e /run/udev/links/test ]]
+[[ ! -e /run/udev/tags/test ]]
+EOF
+
 exit 0