summaryrefslogtreecommitdiffstats
path: root/src/udev/udev-event.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/udev/udev-event.c146
1 files changed, 93 insertions, 53 deletions
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index ed22c8b..607071a 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -14,10 +14,10 @@
#include "udev-node.h"
#include "udev-trace.h"
#include "udev-util.h"
-#include "udev-watch.h"
#include "user-util.h"
-UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level) {
+UdevEvent *udev_event_new(sd_device *dev, UdevWorker *worker, EventMode mode) {
+ int log_level = worker ? worker->log_level : log_get_max_level();
UdevEvent *event;
assert(dev);
@@ -27,15 +27,16 @@ UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rt
return NULL;
*event = (UdevEvent) {
+ .worker = worker,
+ .rtnl = worker ? sd_netlink_ref(worker->rtnl) : NULL,
.dev = sd_device_ref(dev),
.birth_usec = now(CLOCK_MONOTONIC),
- .exec_delay_usec = exec_delay_usec,
- .rtnl = sd_netlink_ref(rtnl),
.uid = UID_INVALID,
.gid = GID_INVALID,
.mode = MODE_INVALID,
.log_level_was_debug = log_level == LOG_DEBUG,
.default_log_level = log_level,
+ .event_mode = mode,
};
return event;
@@ -110,6 +111,9 @@ static int rename_netif(UdevEvent *event) {
assert(event);
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
if (!event->name)
return 0; /* No new name is requested. */
@@ -171,6 +175,12 @@ static int rename_netif(UdevEvent *event) {
goto revert;
}
+ r = device_add_property(event->dev_db_clone, "ID_PROCESSING", "1");
+ if (r < 0) {
+ log_device_warning_errno(event->dev_db_clone, r, "Failed to add 'ID_PROCESSING' property: %m");
+ goto revert;
+ }
+
r = device_update_db(event->dev_db_clone);
if (r < 0) {
log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
@@ -197,6 +207,7 @@ static int rename_netif(UdevEvent *event) {
revert:
/* Restore 'dev_db_clone' */
(void) device_add_property(event->dev_db_clone, "ID_RENAMING", NULL);
+ (void) device_add_property(event->dev_db_clone, "ID_PROCESSING", NULL);
(void) device_update_db(event->dev_db_clone);
/* Restore 'dev' */
@@ -215,6 +226,9 @@ static int assign_altnames(UdevEvent *event) {
int ifindex, r;
const char *s;
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
if (strv_isempty(event->altnames))
return 0;
@@ -243,6 +257,9 @@ static int update_devnode(UdevEvent *event) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
r = sd_device_get_devnum(dev, NULL);
if (r == -ENOENT)
return 0;
@@ -276,14 +293,7 @@ static int update_devnode(UdevEvent *event) {
return udev_node_update(dev, event->dev_db_clone);
}
-static int event_execute_rules_on_remove(
- UdevEvent *event,
- int inotify_fd,
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list,
- UdevRules *rules) {
-
+static int event_execute_rules_on_remove(UdevEvent *event, UdevRules *rules) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
@@ -291,22 +301,22 @@ static int event_execute_rules_on_remove(
if (r < 0)
log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m");
- r = device_tag_index(dev, NULL, false);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
-
- r = device_delete_db(dev);
- if (r < 0)
- log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ r = device_tag_index(dev, NULL, false);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
- r = udev_watch_end(inotify_fd, dev);
- if (r < 0)
- log_device_warning_errno(dev, r, "Failed to remove inotify watch, ignoring: %m");
+ r = device_delete_db(dev);
+ if (r < 0)
+ log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
+ }
- r = udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
+ r = udev_rules_apply_to_event(rules, event);
- if (sd_device_get_devnum(dev, NULL) >= 0)
- (void) udev_node_remove(dev);
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ if (sd_device_get_devnum(dev, NULL) >= 0)
+ (void) udev_node_remove(dev);
+ }
return r;
}
@@ -328,19 +338,45 @@ static int copy_all_tags(sd_device *d, sd_device *s) {
return 0;
}
-int udev_event_execute_rules(
- UdevEvent *event,
- int inotify_fd, /* This may be negative */
- usec_t timeout_usec,
- int timeout_signal,
- Hashmap *properties_list,
- UdevRules *rules) {
+static int update_clone(UdevEvent *event) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev_db_clone);
+ int r;
+
+ if (!EVENT_MODE_DESTRUCTIVE(event))
+ return 0;
+
+ /* Drop previously added property for safety to make IMPORT{db}="ID_RENAMING" not work. This is
+ * mostly for 'move' uevent, but let's do unconditionally. Why? If a network interface is renamed in
+ * initrd, then udevd may lose the 'move' uevent during switching root. Usually, we do not set the
+ * persistent flag for network interfaces, but user may set it. Just for safety. */
+ r = device_add_property(dev, "ID_RENAMING", NULL);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
+
+ /* If the database file already exists, append ID_PROCESSING property to the existing database,
+ * to indicate that the device is being processed by udevd. */
+ if (device_has_db(dev) > 0) {
+ r = device_add_property(dev, "ID_PROCESSING", "1");
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to add 'ID_PROCESSING' property: %m");
+
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ }
+
+ return 0;
+}
+
+int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) {
sd_device_action_t action;
sd_device *dev;
int r;
- dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+ assert(event);
+ assert(IN_SET(event->event_mode, EVENT_UDEV_WORKER, EVENT_UDEVADM_TEST, EVENT_TEST_RULE_RUNNER));
+ dev = ASSERT_PTR(event->dev);
assert(rules);
r = sd_device_get_action(dev, &action);
@@ -348,12 +384,7 @@ int udev_event_execute_rules(
return log_device_error_errno(dev, r, "Failed to get ACTION: %m");
if (action == SD_DEVICE_REMOVE)
- return event_execute_rules_on_remove(event, inotify_fd, timeout_usec, timeout_signal, properties_list, rules);
-
- /* Disable watch during event processing. */
- r = udev_watch_end(inotify_fd, dev);
- if (r < 0)
- log_device_warning_errno(dev, r, "Failed to remove inotify watch, ignoring: %m");
+ return event_execute_rules_on_remove(event, rules);
r = device_clone_with_db(dev, &event->dev_db_clone);
if (r < 0)
@@ -363,17 +394,13 @@ int udev_event_execute_rules(
if (r < 0)
log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m");
- /* Drop previously added property for safety to make IMPORT{db}="ID_RENAMING" not work. This is
- * mostly for 'move' uevent, but let's do unconditionally. Why? If a network interface is renamed in
- * initrd, then udevd may lose the 'move' uevent during switching root. Usually, we do not set the
- * persistent flag for network interfaces, but user may set it. Just for safety. */
- r = device_add_property(event->dev_db_clone, "ID_RENAMING", NULL);
+ r = update_clone(event);
if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
+ return r;
DEVICE_TRACE_POINT(rules_start, dev);
- r = udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
+ r = udev_rules_apply_to_event(rules, event);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to apply udev rules: %m");
@@ -396,14 +423,27 @@ int udev_event_execute_rules(
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to set initialization timestamp: %m");
- /* (re)write database file */
- r = device_tag_index(dev, event->dev_db_clone, true);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ /* (re)write database file */
+ r = device_tag_index(dev, event->dev_db_clone, true);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
+ }
- r = device_update_db(dev);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ /* If the database file for the device will be created below, add ID_PROCESSING=1 to indicate that
+ * the device is still being processed by udevd, as commands specified in RUN are invoked after
+ * the database is created. See issue #30056. */
+ if (device_should_have_db(dev) && !ordered_hashmap_isempty(event->run_list)) {
+ r = device_add_property(dev, "ID_PROCESSING", "1");
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to add 'ID_PROCESSING' property: %m");
+ }
+
+ if (EVENT_MODE_DESTRUCTIVE(event)) {
+ r = device_update_db(dev);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
+ }
device_set_is_initialized(dev);