[systemd-commits] 6 commits - src/libudev src/udev

Tom Gundersen tomegun at kemper.freedesktop.org
Thu Mar 12 04:08:44 PDT 2015


 src/libudev/libudev-device-private.c |    1 +
 src/libudev/libudev-device.c         |   29 +++++++++++++++++++++++++++++
 src/libudev/libudev-monitor.c        |   10 +++++++++-
 src/libudev/libudev-private.h        |    2 ++
 src/udev/udev-event.c                |   26 ++++++--------------------
 src/udev/udevd.c                     |   13 +++++++++----
 6 files changed, 56 insertions(+), 25 deletions(-)

New commits:
commit 6969c349df91a3cc5fc2cf559a14e32a84db969d
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Mar 11 15:41:32 2015 +0100

    udevd: improve handling of failed worker
    
    The information in the db is stale, so it does not make sense to
    expose it any longer. Also, don't drop the kernel event, but simply
    pass it on to userspace without ammending it.

diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 9426edc..ac21d51 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -83,6 +83,7 @@ struct event {
         struct udev_list_node node;
         struct udev *udev;
         struct udev_device *dev;
+        struct udev_device *dev_kernel;
         enum event_state state;
         int exitcode;
         unsigned long long int delaying_seqnum;
@@ -133,6 +134,7 @@ static inline struct worker *node_to_worker(struct udev_list_node *node) {
 static void event_queue_delete(struct event *event) {
         udev_list_node_remove(&event->node);
         udev_device_unref(event->dev);
+        udev_device_unref(event->dev_kernel);
         free(event);
 }
 
@@ -459,6 +461,8 @@ static int event_queue_insert(struct udev_device *dev) {
 
         event->udev = udev_device_get_udev(dev);
         event->dev = dev;
+        event->dev_kernel = udev_device_shallow_clone(dev);
+        udev_device_copy_properties(event->dev_kernel, dev);
         event->seqnum = udev_device_get_seqnum(dev);
         event->devpath = udev_device_get_devpath(dev);
         event->devpath_len = strlen(event->devpath);
@@ -886,6 +890,11 @@ static void handle_signal(struct udev *udev, int signo) {
                                                 log_error("worker ["PID_FMT"] failed while handling '%s'",
                                                           pid, worker->event->devpath);
                                                 worker->event->exitcode = -32;
+                                                /* delete state from disk */
+                                                udev_device_delete_db(worker->event->dev);
+                                                udev_device_tag_index(worker->event->dev, NULL, false);
+                                                /* forward kernel event without ammending it */
+                                                udev_monitor_send_device(monitor, NULL, worker->event->dev_kernel);
                                                 event_queue_delete(worker->event);
 
                                                 /* drop reference taken for state 'running' */

commit 090b6bc5205b924df4be3239b2f7d9c097fbb705
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Mar 11 22:27:46 2015 +0100

    udevd: don't free event when killing the worker, wait until it has been reaped
    
    This will allow us to clean up the device when we are notified about the worker being killed.

diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index c01fb4b..9426edc 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1414,12 +1414,8 @@ int main(int argc, char *argv[]) {
                                                 kill(worker->pid, SIGKILL);
                                                 worker->state = WORKER_KILLED;
 
-                                                /* drop reference taken for state 'running' */
-                                                worker_unref(worker);
                                                 log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
                                                 worker->event->exitcode = -64;
-                                                event_queue_delete(worker->event);
-                                                worker->event = NULL;
                                         } else if (!worker->event_warned) {
                                                 log_warning("worker ["PID_FMT"] %s is taking a long time", worker->pid, worker->event->devpath);
                                                 worker->event_warned = true;

commit 8f0f13f04555d3bc67511d2e334c667cef7e8971
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Mar 6 15:22:30 2015 +0100

    libudev: introduce clone_with_db()
    
    This allows us to move the db reading from udevd to libudev.

diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 2604ad7..c0a061a 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -1986,6 +1986,20 @@ struct udev_device *udev_device_shallow_clone(struct udev_device *old_device)
         return device;
 }
 
+struct udev_device *udev_device_clone_with_db(struct udev_device *old_device)
+{
+        struct udev_device *device;
+
+        device = udev_device_shallow_clone(old_device);
+        if (!device)
+                return NULL;
+
+        udev_device_read_db(device);
+        udev_device_set_info_loaded(device);
+
+        return device;
+}
+
 struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) {
         struct udev_device *device;
         ssize_t bufpos = 0;
diff --git a/src/libudev/libudev-private.h b/src/libudev/libudev-private.h
index c0f9fbe..a34c0f7 100644
--- a/src/libudev/libudev-private.h
+++ b/src/libudev/libudev-private.h
@@ -39,6 +39,7 @@ int udev_get_rules_path(struct udev *udev, char **path[], usec_t *ts_usec[]);
 /* libudev-device.c */
 struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen);
 struct udev_device *udev_device_shallow_clone(struct udev_device *old_device);
+struct udev_device *udev_device_clone_with_db(struct udev_device *old_device);
 int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src);
 mode_t udev_device_get_devnode_mode(struct udev_device *udev_device);
 uid_t udev_device_get_devnode_uid(struct udev_device *udev_device);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 4ca73d3..f62c1ea 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -807,11 +807,8 @@ void udev_event_execute_rules(struct udev_event *event,
                 udev_device_delete_db(dev);
                 udev_device_tag_index(dev, NULL, false);
         } else {
-                event->dev_db = udev_device_shallow_clone(dev);
+                event->dev_db = udev_device_clone_with_db(dev);
                 if (event->dev_db != NULL) {
-                        udev_device_read_db(event->dev_db);
-                        udev_device_set_info_loaded(event->dev_db);
-
                         /* disable watch during event processing */
                         if (major(udev_device_get_devnum(dev)) != 0)
                                 udev_watch_end(event->udev, event->dev_db);

commit a4445e88cece0444c66d70876b03065158dd4685
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Mar 11 22:23:38 2015 +0100

    libudev: monitor - fix error path in send_device
    
    Return -errno rather than -1 in case sendmsg() fails.

diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index eb7b6f8..0c554bb 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -745,12 +745,20 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
          * If we send to a multicast group, we will get
          * ECONNREFUSED, which is expected.
          */
-        if (destination != NULL)
+        if (destination)
                 smsg.msg_name = &destination->snl;
         else
                 smsg.msg_name = &udev_monitor->snl_destination;
         smsg.msg_namelen = sizeof(struct sockaddr_nl);
         count = sendmsg(udev_monitor->sock, &smsg, 0);
+        if (count < 0) {
+                if (!destination && errno == ECONNREFUSED) {
+                        log_debug("passed unknown number of bytes to netlink monitor %p", udev_monitor);
+                        return 0;
+                } else
+                        return -errno;
+        }
+
         log_debug("passed %zi bytes to netlink monitor %p", count, udev_monitor);
         return count;
 }

commit 3c0bab4aaf70b2383aa4cbabf6059c48744e8960
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Mar 6 18:22:35 2015 +0100

    udevd: event - make db loading lazy in REMOVE event handling
    
    We were explicitly eagerly loading the db, then deletenig the backing file and then processing the
    rules/symlinks. Instead we delete the backnig db file as the last step and let the db loading be
    lazy as everywhere else.
    
    This may save us a bit of work in casese where the db is not needed, but more importantly it hides
    some implementation details of libudev-device form udevd.

diff --git a/src/libudev/libudev-device-private.c b/src/libudev/libudev-device-private.c
index 15d3b23..e590288 100644
--- a/src/libudev/libudev-device-private.c
+++ b/src/libudev/libudev-device-private.c
@@ -182,6 +182,7 @@ int udev_device_delete_db(struct udev_device *udev_device)
         if (id == NULL)
                 return -1;
         strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
+
         unlink(filename);
         return 0;
 }
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index b96cf73..4ca73d3 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -793,10 +793,6 @@ void udev_event_execute_rules(struct udev_event *event,
                 return;
 
         if (streq(udev_device_get_action(dev), "remove")) {
-                udev_device_read_db(dev);
-                udev_device_delete_db(dev);
-                udev_device_tag_index(dev, NULL, false);
-
                 if (major(udev_device_get_devnum(dev)) != 0)
                         udev_watch_end(event->udev, dev);
 
@@ -807,6 +803,9 @@ void udev_event_execute_rules(struct udev_event *event,
 
                 if (major(udev_device_get_devnum(dev)) != 0)
                         udev_node_remove(dev);
+
+                udev_device_delete_db(dev);
+                udev_device_tag_index(dev, NULL, false);
         } else {
                 event->dev_db = udev_device_shallow_clone(dev);
                 if (event->dev_db != NULL) {

commit 1cd0a77022a4da17d1274f8f776b63e72c99fb05
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Mar 6 18:30:09 2015 +0100

    libudev: introduce udev_device_properties_copy()
    
    To copy properties from one device to another. Drop the equivalent functionality from udevd.

diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 242a0d8..2604ad7 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -2030,3 +2030,18 @@ struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr,
 
         return device;
 }
+
+int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src) {
+        struct udev_list_entry *entry;
+
+        for ((entry = udev_device_get_properties_list_entry(src)); entry; entry = udev_list_entry_get_next(entry)) {
+                const char *key, *value;
+
+                key = udev_list_entry_get_name(entry);
+                value = udev_list_entry_get_value(entry);
+
+                udev_device_add_property(dst, key, value);
+        }
+
+        return 0;
+}
diff --git a/src/libudev/libudev-private.h b/src/libudev/libudev-private.h
index 9153e67..c0f9fbe 100644
--- a/src/libudev/libudev-private.h
+++ b/src/libudev/libudev-private.h
@@ -39,6 +39,7 @@ int udev_get_rules_path(struct udev *udev, char **path[], usec_t *ts_usec[]);
 /* libudev-device.c */
 struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen);
 struct udev_device *udev_device_shallow_clone(struct udev_device *old_device);
+int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src);
 mode_t udev_device_get_devnode_mode(struct udev_device *udev_device);
 uid_t udev_device_get_devnode_uid(struct udev_device *udev_device);
 gid_t udev_device_get_devnode_gid(struct udev_device *udev_device);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 67fb1f7..b96cf73 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -819,18 +819,8 @@ void udev_event_execute_rules(struct udev_event *event,
                 }
 
                 if (major(udev_device_get_devnum(dev)) == 0 &&
-                    streq(udev_device_get_action(dev), "move")) {
-                        struct udev_list_entry *entry;
-
-                        for ((entry = udev_device_get_properties_list_entry(event->dev_db)); entry; entry = udev_list_entry_get_next(entry)) {
-                                const char *key, *value;
-
-                                key = udev_list_entry_get_name(entry);
-                                value = udev_list_entry_get_value(entry);
-
-                                udev_device_add_property(dev, key, value);
-                        }
-                }
+                    streq(udev_device_get_action(dev), "move"))
+                        udev_device_copy_properties(dev, event->dev_db);
 
                 udev_rules_apply_to_event(rules, event,
                                           timeout_usec, timeout_warn_usec,



More information about the systemd-commits mailing list