chiark / gitweb /
move /dev/.udev/ to /dev/.run/udev/ and convert old udev database at udevd startup
authorKay Sievers <kay.sievers@vrfy.org>
Tue, 15 Mar 2011 16:26:08 +0000 (17:26 +0100)
committerKay Sievers <kay.sievers@vrfy.org>
Tue, 15 Mar 2011 16:26:08 +0000 (17:26 +0100)
18 files changed:
Makefile.am
NEWS
extras/collect/collect.c
extras/firmware/firmware.c
libudev/libudev-device-private.c
libudev/libudev-device.c
libudev/libudev-enumerate.c
libudev/libudev-private.h
libudev/libudev-queue-private.c
libudev/libudev-queue.c
udev/udev-event.c
udev/udev-node.c
udev/udev-rules.c
udev/udev-watch.c
udev/udev.xml
udev/udevadm-info.c
udev/udevadm.xml
udev/udevd.c

index 62c3bdb..15d1636 100644 (file)
@@ -35,7 +35,7 @@ DISTCHECK_HOOKS =
 # libudev
 # ------------------------------------------------------------------------------
 LIBUDEV_CURRENT=11
-LIBUDEV_REVISION=0
+LIBUDEV_REVISION=1
 LIBUDEV_AGE=11
 
 SUBDIRS += libudev/docs
diff --git a/NEWS b/NEWS
index b5008db..fcb6c75 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,18 @@ udev 167
 ========
 Bugfixes.
 
+The udev runtime data moved from /dev/.udev/ to /dev/.run/udev/.
+On new systems the tmpfs mountpoint /var/run/ will have an
+"early-boot alias" /dev/.run/ where udev and a couple of other
+early-boot tools will put their runtime data.
+On systems with LVM used, packagers must make sure, that the
+initramfs creates the /dev/.run/ mountpoint for udev to store
+the data, so that the real root will not overmount it, which
+would make it invisible.
+
+The command 'udevadm info --convert-db' is gone. The udev daemon
+itself, at startup, converts any old database version if necessary.
+
 udev 166
 ========
 Bugfixes.
index 0069dea..b567051 100644 (file)
@@ -34,7 +34,7 @@
 #include "libudev.h"
 #include "libudev-private.h"
 
-#define TMPFILE                        "/dev/.udev/collect"
+#define TMPFILE                        "/dev/.run/udev/collect"
 #define BUFSIZE                        16
 #define UDEV_ALARM_TIMEOUT     180
 
index 76593ba..f7d21df 100644 (file)
@@ -147,7 +147,7 @@ int main(int argc, char **argv)
        }
 
        util_path_encode(firmware, fwencpath, sizeof(fwencpath));
-       util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.udev/firmware-missing/", fwencpath, NULL);
+       util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.run/udev/firmware-missing/", fwencpath, NULL);
        util_strscpyl(loadpath, sizeof(loadpath), udev_get_sys_path(udev), devpath, "/loading", NULL);
 
        if (fwfile == NULL) {
index 3afa82e..7683f09 100644 (file)
@@ -31,7 +31,7 @@ static void udev_device_tag(struct udev_device *dev, const char *tag, bool add)
        id = udev_device_get_id_filename(dev);
        if (id == NULL)
                return;
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/tags/", tag, "/", id, NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/tags/", tag, "/", id, NULL);
 
        if (add) {
                int fd;
@@ -115,7 +115,7 @@ int udev_device_update_db(struct udev_device *udev_device)
                return -1;
 
        has_info = device_has_info(udev_device);
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL);
 
        /* do not store anything for otherwise empty devices */
        if (!has_info &&
@@ -176,7 +176,7 @@ int udev_device_delete_db(struct udev_device *udev_device)
        id = udev_device_get_id_filename(udev_device);
        if (id == NULL)
                return -1;
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL);
        unlink(filename);
        return 0;
 }
index c78cf9b..dd0224a 100644 (file)
@@ -237,24 +237,30 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons
        return udev_list_entry_get_value(list_entry);
 }
 
-int udev_device_read_db(struct udev_device *udev_device)
+int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
 {
-       const char *id;
        char filename[UTIL_PATH_SIZE];
        char line[UTIL_LINE_SIZE];
        FILE *f;
 
-       if (udev_device->db_loaded)
-               return 0;
-       udev_device->db_loaded = true;
+       /* providing a database file will always force-load it */
+       if (dbfile == NULL) {
+               const char *id;
 
-       id = udev_device_get_id_filename(udev_device);
-       if (id == NULL)
-               return -1;
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.udev/db/", id, NULL);
-       f = fopen(filename, "re");
+               if (udev_device->db_loaded)
+                       return 0;
+               udev_device->db_loaded = true;
+
+               id = udev_device_get_id_filename(udev_device);
+               if (id == NULL)
+                       return -1;
+               util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.run/udev/db3/", id, NULL);
+               dbfile = filename;
+       }
+
+       f = fopen(dbfile, "re");
        if (f == NULL) {
-               info(udev_device->udev, "no db file to read %s: %m\n", filename);
+               info(udev_device->udev, "no db file to read %s: %m\n", dbfile);
                return -1;
        }
        udev_device->is_initialized = true;
@@ -908,7 +914,7 @@ const char *udev_device_get_devnode(struct udev_device *udev_device)
                return NULL;
        if (!udev_device->info_loaded) {
                udev_device_read_uevent_file(udev_device);
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        }
 
        /* we might get called before we handled an event and have a db, use the kernel-provided name */
@@ -1002,7 +1008,7 @@ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *
        if (udev_device == NULL)
                return NULL;
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        return udev_list_get_entry(&udev_device->devlinks_list);
 }
 
@@ -1030,7 +1036,7 @@ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device
                return NULL;
        if (!udev_device->info_loaded) {
                udev_device_read_uevent_file(udev_device);
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        }
        if (!udev_device->devlinks_uptodate) {
                char symlinks[UTIL_PATH_SIZE];
@@ -1154,7 +1160,7 @@ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device
        if (udev_device == NULL)
                return 0;
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        if (udev_device->usec_initialized == 0)
                return 0;
        now = usec_monotonic();
@@ -1471,7 +1477,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
 int udev_device_get_is_initialized(struct udev_device *udev_device)
 {
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        return udev_device->is_initialized;
 }
 
@@ -1519,7 +1525,7 @@ int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
        struct udev_list_entry *list_entry;
 
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        list_entry = udev_device_get_tags_list_entry(udev_device);
        list_entry =  udev_list_entry_get_by_name(list_entry, tag);
        if (list_entry != NULL)
@@ -1689,7 +1695,7 @@ int udev_device_set_timeout(struct udev_device *udev_device, int timeout)
 int udev_device_get_event_timeout(struct udev_device *udev_device)
 {
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        return udev_device->event_timeout;
 }
 
@@ -1729,7 +1735,7 @@ int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
 int udev_device_get_devlink_priority(struct udev_device *udev_device)
 {
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        return udev_device->devlink_priority;
 }
 
@@ -1742,7 +1748,7 @@ int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
 int udev_device_get_watch_handle(struct udev_device *udev_device)
 {
        if (!udev_device->info_loaded)
-               udev_device_read_db(udev_device);
+               udev_device_read_db(udev_device, NULL);
        return udev_device->watch_handle;
 }
 
index 128813c..d3dd5c9 100644 (file)
@@ -751,7 +751,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
                        struct dirent *dent;
                        char path[UTIL_PATH_SIZE];
 
-                       util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.udev/tags/",
+                       util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.run/udev/tags/",
                                      udev_list_entry_get_name(list_entry), NULL);
                        dir = opendir(path);
                        if (dir == NULL)
index f95be53..0fe6f4a 100644 (file)
@@ -78,7 +78,7 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
 int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device);
 char **udev_device_get_properties_envp(struct udev_device *udev_device);
 ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf);
-int udev_device_read_db(struct udev_device *udev_device);
+int udev_device_read_db(struct udev_device *udev_device, const char *dbfile);
 int udev_device_read_uevent_file(struct udev_device *udev_device);
 int udev_device_set_action(struct udev_device *udev_device, const char *action);
 int udev_device_set_driver(struct udev_device *udev_device, const char *driver);
index 06dc2f5..9b02daf 100644 (file)
@@ -103,10 +103,10 @@ void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export)
 {
        char filename[UTIL_PATH_SIZE];
 
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL);
        unlink(filename);
 
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL);
        unlink(filename);
 }
 
@@ -221,7 +221,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export)
        }
 
        /* create new queue file */
-       util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL);
+       util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL);
        new_queue_file = fopen(filename_tmp, "w+");
        if (new_queue_file == NULL)
                goto error;
@@ -255,7 +255,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export)
                goto error;
 
        /* rename the new file on top of the old one */
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL);
        if (rename(filename_tmp, filename) != 0)
                goto error;
 
@@ -401,7 +401,7 @@ static void update_failed(struct udev_queue_export *udev_queue_export,
                return;
 
        /* location of failed file */
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/failed/",
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/failed/",
                      udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL);
 
        switch (state) {
index 163e622..6f743d2 100644 (file)
@@ -214,7 +214,7 @@ static FILE *open_queue_file(struct udev_queue *udev_queue, unsigned long long i
        char filename[UTIL_PATH_SIZE];
        FILE *queue_file;
 
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/queue.bin", NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.run/udev/queue.bin", NULL);
        queue_file = fopen(filename, "re");
        if (queue_file == NULL)
                return NULL;
@@ -484,7 +484,7 @@ struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev
        if (udev_queue == NULL)
                return NULL;
        udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list);
-       util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.udev/failed", NULL);
+       util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.run/udev/failed", NULL);
        dir = opendir(path);
        if (dir == NULL)
                return NULL;
index 100a79c..137ba36 100644 (file)
@@ -539,7 +539,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
                return -1;
 
        if (strcmp(udev_device_get_action(dev), "remove") == 0) {
-               udev_device_read_db(dev);
+               udev_device_read_db(dev, NULL);
                udev_device_delete_db(dev);
                udev_device_tag_index(dev, NULL, false);
 
@@ -553,7 +553,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
        } else {
                event->dev_db = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev));
                if (event->dev_db != NULL) {
-                       udev_device_read_db(event->dev_db);
+                       udev_device_read_db(event->dev_db, NULL);
                        udev_device_set_info_loaded(event->dev_db);
 
                        /* disable watch during event processing */
index 0ceb1d5..aaa2e32 100644 (file)
@@ -292,7 +292,7 @@ static void link_update(struct udev_device *dev, const char *slink, bool add)
        dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev));
 
        util_path_encode(&slink[strlen(udev_get_dev_path(udev))+1], name_enc, sizeof(name_enc));
-       util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.udev/links/", name_enc, NULL);
+       util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.run/udev/links/", name_enc, NULL);
        util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
 
        if (!add) {
index 6b473c4..4a5b8de 100644 (file)
@@ -1803,7 +1803,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
                add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules");
 
                /* read dynamic/temporary rules */
-               util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
+               util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL);
                udev_list_init(&sort_list);
                add_matching_files(udev, &sort_list, filename, ".rules");
 
index f51a10d..47dca4c 100644 (file)
@@ -54,8 +54,8 @@ void udev_watch_restore(struct udev *udev)
        if (inotify_fd < 0)
                return;
 
-       util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.udev/watch.old", NULL);
-       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/watch", NULL);
+       util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.run/udev/watch.old", NULL);
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/watch", NULL);
        if (rename(filename, oldname) == 0) {
                DIR *dir;
                struct dirent *ent;
@@ -118,7 +118,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev)
                return;
        }
 
-       snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
+       snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
        util_create_path(udev, filename);
        unlink(filename);
        symlink(udev_device_get_id_filename(dev), filename);
@@ -141,7 +141,7 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev)
        info(udev, "removing watch on '%s'\n", udev_device_get_devnode(dev));
        inotify_rm_watch(inotify_fd, wd);
 
-       snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
+       snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
        unlink(filename);
 
        udev_device_set_watch_handle(dev, -1);
@@ -158,7 +158,7 @@ struct udev_device *udev_watch_lookup(struct udev *udev, int wd)
        if (inotify_fd < 0 || wd < 0)
                return NULL;
 
-       snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
+       snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
        s = majmin;
        l = util_strpcpy(&s, sizeof(majmin), udev_get_sys_path(udev));
        len = readlink(filename, s, l);
index 3ef4103..452abc5 100644 (file)
@@ -73,7 +73,7 @@
       <para>The udev rules are read from the files located in the
       default rules directory <filename>/lib/udev/rules.d/</filename>,
       the custom rules directory <filename>/etc/udev/rules.d/</filename>
-      and the temporary rules directory <filename>/dev/.udev/rules.d/</filename>.
+      and the temporary rules directory <filename>/var/run/udev/rules.d/</filename>.
       All rule files are sorted and processed in lexical order, regardless
       in which of these directories they live. Files in
       <filename>/etc/udev/rules.d/</filename> have precedence over files with
index 187e74d..33d113c 100644 (file)
@@ -200,66 +200,6 @@ static int export_devices(struct udev *udev)
        return 0;
 }
 
-static int convert_db(struct udev *udev)
-{
-       struct udev_enumerate *udev_enumerate;
-       struct udev_list_entry *list_entry;
-
-       udev_enumerate = udev_enumerate_new(udev);
-       if (udev_enumerate == NULL)
-               return -1;
-       udev_enumerate_scan_devices(udev_enumerate);
-       udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
-               struct udev_device *device;
-
-               device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
-               if (device != NULL) {
-                       const char *id;
-                       struct stat stats;
-                       char to[UTIL_PATH_SIZE];
-                       char devpath[UTIL_PATH_SIZE];
-                       char from[UTIL_PATH_SIZE];
-
-                       id = udev_device_get_id_filename(device);
-                       if (id == NULL) {
-                               udev_device_unref(device);
-                               continue;
-                       }
-                       util_strscpyl(to, sizeof(to), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
-
-                       /* find old database with $subsys:$sysname */
-                       util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
-                                    "/.udev/db/", udev_device_get_subsystem(device), ":",
-                                    udev_device_get_sysname(device), NULL);
-                       if (lstat(from, &stats) == 0) {
-                               if (lstat(to, &stats) == 0)
-                                       unlink(from);
-                               else
-                                       rename(from, to);
-                       }
-
-                       /* find old database with the encoded devpath */
-                       util_path_encode(udev_device_get_devpath(device), devpath, sizeof(devpath));
-                       util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
-                                     "/.udev/db/", devpath, NULL);
-                       if (lstat(from, &stats) == 0) {
-                               if (lstat(to, &stats) == 0)
-                                       unlink(from);
-                               else
-                                       rename(from, to);
-                       }
-
-                       /* read the old database, and write out a new one */
-                       udev_device_read_db(device);
-                       udev_device_update_db(device);
-
-                       udev_device_unref(device);
-               }
-       }
-       udev_enumerate_unref(udev_enumerate);
-       return 0;
-}
-
 int udevadm_info(struct udev *udev, int argc, char *argv[])
 {
        struct udev_device *device = NULL;
@@ -277,7 +217,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                { "query", required_argument, NULL, 'q' },
                { "attribute-walk", no_argument, NULL, 'a' },
                { "export-db", no_argument, NULL, 'e' },
-               { "convert-db", no_argument, NULL, 'C' },
                { "root", no_argument, NULL, 'r' },
                { "device-id-of-file", required_argument, NULL, 'd' },
                { "export", no_argument, NULL, 'x' },
@@ -402,9 +341,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                case 'e':
                        export_devices(udev);
                        goto exit;
-               case 'C':
-                       convert_db(udev);
-                       goto exit;
                case 'x':
                        export = true;
                        break;
@@ -431,7 +367,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                               "  --export                   export key/value pairs\n"
                               "  --export-prefix            export the key name with a prefix\n"
                               "  --export-db                export the content of the udev database\n"
-                              "  --convert-db               convert older version of database without a reboot\n"
                               "  --help\n\n");
                        goto exit;
                default:
index 00f299f..cefd776 100644 (file)
           </listitem>
         </varlistentry>
         <varlistentry>
-          <term><option>--convert-db</option></term>
-          <listitem>
-            <para>Convert the database of an earlier udev version to the current format. This
-            is only useful on udev version upgrades, where the content of the old database might
-            be needed for the running system, and it is not sufficient for it, to be re-created
-            with the next bootup.</para>
-          </listitem>
-        </varlistentry>
-        <varlistentry>
           <term><option>--version</option></term>
           <listitem>
             <para>Print version.</para>
index aa2e365..fe0e3c3 100644 (file)
@@ -971,6 +971,99 @@ static int mem_size_mb(void)
        return memsize;
 }
 
+static int convert_db(struct udev *udev)
+{
+       char filename[UTIL_PATH_SIZE];
+       FILE *f;
+       struct udev_enumerate *udev_enumerate;
+       struct udev_list_entry *list_entry;
+
+       /* current database */
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3", NULL);
+       if (access(filename, F_OK) >= 0)
+               return 0;
+
+       /* make sure we do not get here again */
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", NULL);
+       util_create_path(udev, filename);
+
+       /* old database */
+       util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db", NULL);
+       if (access(filename, F_OK) < 0)
+               return 0;
+
+       f = fopen("/dev/kmsg", "w");
+       if (f != NULL) {
+               fprintf(f, "<6>udev[%u]: converting old udev database\n", getpid());
+               fclose(f);
+       }
+
+       udev_enumerate = udev_enumerate_new(udev);
+       if (udev_enumerate == NULL)
+               return -1;
+       udev_enumerate_scan_devices(udev_enumerate);
+       udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
+               struct udev_device *device;
+
+               device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
+               if (device == NULL)
+                       continue;
+
+               /* try to find the old database for devices without a current one */
+               if (udev_device_read_db(device, NULL) < 0) {
+                       bool have_db;
+                       const char *id;
+                       struct stat stats;
+                       char devpath[UTIL_PATH_SIZE];
+                       char from[UTIL_PATH_SIZE];
+
+                       have_db = false;
+
+                       /* find database in old location */
+                       id = udev_device_get_id_filename(device);
+                       util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+                       if (lstat(from, &stats) == 0) {
+                               if (!have_db) {
+                                       udev_device_read_db(device, from);
+                                       have_db = true;
+                               }
+                               unlink(from);
+                       }
+
+                       /* find old database with $subsys:$sysname name */
+                       util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
+                                    "/.udev/db/", udev_device_get_subsystem(device), ":",
+                                    udev_device_get_sysname(device), NULL);
+                       if (lstat(from, &stats) == 0) {
+                               if (!have_db) {
+                                       udev_device_read_db(device, from);
+                                       have_db = true;
+                               }
+                               unlink(from);
+                       }
+
+                       /* find old database with the encoded devpath name */
+                       util_path_encode(udev_device_get_devpath(device), devpath, sizeof(devpath));
+                       util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
+                                     "/.udev/db/", devpath, NULL);
+                       if (lstat(from, &stats) == 0) {
+                               if (!have_db) {
+                                       udev_device_read_db(device, from);
+                                       have_db = true;
+                               }
+                               unlink(from);
+                       }
+
+                       /* write out new database */
+                       if (have_db)
+                               udev_device_update_db(device);
+               }
+               udev_device_unref(device);
+       }
+       udev_enumerate_unref(udev_enumerate);
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        struct udev *udev;
@@ -1159,7 +1252,7 @@ int main(int argc, char *argv[])
                                  IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
 
                /* watch dynamic rules directory */
-               util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
+               util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL);
                if (stat(filename, &statbuf) != 0) {
                        util_create_path(udev, filename);
                        udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755);
@@ -1203,6 +1296,9 @@ int main(int argc, char *argv[])
                goto exit;
        }
 
+       /* if needed, convert old database from earlier udev version */
+       convert_db(udev);
+
        if (!debug) {
                dup2(fd, STDIN_FILENO);
                dup2(fd, STDOUT_FILENO);