]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: move timeout event sources from struct Event to struct Worker
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 6 May 2025 10:23:53 +0000 (19:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 9 May 2025 15:26:32 +0000 (00:26 +0900)
The timeout event sources are enabled only when the event is being
processed by a worker, hence they are not necessary to be owned by the
event.

No effective functional change, just refactoring.

src/udev/udev-manager.c

index 504fdf2abfc48efdf6b932a65fdcb54d971fdbeb..d883e0f67208dc5335ad2b48c26f128cee6c278a 100644 (file)
@@ -67,9 +67,6 @@ typedef struct Event {
         usec_t retry_again_timeout_usec;
         sd_event_source *retry_event_source;
 
-        sd_event_source *timeout_warning_event;
-        sd_event_source *timeout_event;
-
         bool dependencies_built;
         Set *blocker_events;
         Set *blocking_events;
@@ -88,6 +85,8 @@ typedef struct Worker {
         Manager *manager;
         PidRef pidref;
         sd_event_source *child_event_source;
+        sd_event_source *timeout_warning_event_source;
+        sd_event_source *timeout_kill_event_source;
         union sockaddr_union address;
         WorkerState state;
         Event *event;
@@ -126,8 +125,6 @@ static Event* event_free(Event *event) {
         sd_device_unref(event->dev);
 
         sd_event_source_unref(event->retry_event_source);
-        sd_event_source_unref(event->timeout_warning_event);
-        sd_event_source_unref(event->timeout_event);
 
         return mfree(event);
 }
@@ -142,6 +139,8 @@ static Worker* worker_free(Worker *worker) {
                 hashmap_remove(worker->manager->workers, &worker->pidref);
 
         sd_event_source_disable_unref(worker->child_event_source);
+        sd_event_source_unref(worker->timeout_warning_event_source);
+        sd_event_source_unref(worker->timeout_kill_event_source);
         pidref_done(&worker->pidref);
         event_free(worker->event);
 
@@ -439,36 +438,33 @@ static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_
         return 0;
 }
 
-static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
-        Event *event = ASSERT_PTR(userdata);
-
-        assert(event->manager);
-        assert(event->worker);
-
-        (void) pidref_kill_and_sigcont(&event->worker->pidref, event->manager->config.timeout_signal);
-        event->worker->state = WORKER_KILLED;
+static int on_worker_timeout_kill(sd_event_source *s, uint64_t usec, void *userdata) {
+        Worker *worker = ASSERT_PTR(userdata);
+        Manager *manager = ASSERT_PTR(worker->manager);
+        Event *event = ASSERT_PTR(worker->event);
 
-        log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed.", event->worker->pidref.pid, event->seqnum);
+        (void) pidref_kill_and_sigcont(&worker->pidref, manager->config.timeout_signal);
+        worker->state = WORKER_KILLED;
 
-        return 1;
+        log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed.", worker->pidref.pid, event->seqnum);
+        return 0;
 }
 
-static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
-        Event *event = ASSERT_PTR(userdata);
-
-        assert(event->worker);
-
-        log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time.", event->worker->pidref.pid, event->seqnum);
+static int on_worker_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
+        Worker *worker = ASSERT_PTR(userdata);
+        Event *event = ASSERT_PTR(worker->event);
 
-        return 1;
+        log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time.", worker->pidref.pid, event->seqnum);
+        return 0;
 }
 
 static void worker_attach_event(Worker *worker, Event *event) {
         Manager *manager = ASSERT_PTR(ASSERT_PTR(worker)->manager);
-        sd_event *e = ASSERT_PTR(manager->event);
 
         assert(event);
+        assert(event->state == EVENT_QUEUED);
         assert(!event->worker);
+        assert(IN_SET(worker->state, WORKER_UNDEF, WORKER_IDLE));
         assert(!worker->event);
 
         worker->state = WORKER_RUNNING;
@@ -477,29 +473,46 @@ static void worker_attach_event(Worker *worker, Event *event) {
         event->worker = worker;
 
         (void) event_reset_time_relative(
-                        e,
-                        &event->timeout_warning_event,
+                        manager->event,
+                        &worker->timeout_warning_event_source,
                         CLOCK_MONOTONIC,
                         udev_warn_timeout(manager->config.timeout_usec),
                         USEC_PER_SEC,
-                        on_event_timeout_warning,
-                        event,
+                        on_worker_timeout_warning,
+                        worker,
                         EVENT_PRIORITY_WORKER_TIMER,
-                        "event-timeout-warn",
+                        "worker-timeout-warn",
                         /* force_reset = */ true);
 
         (void) event_reset_time_relative(
-                        e,
-                        &event->timeout_event, CLOCK_MONOTONIC,
+                        manager->event,
+                        &worker->timeout_kill_event_source,
+                        CLOCK_MONOTONIC,
                         manager_kill_worker_timeout(manager),
                         USEC_PER_SEC,
-                        on_event_timeout,
-                        event,
+                        on_worker_timeout_kill,
+                        worker,
                         EVENT_PRIORITY_WORKER_TIMER,
-                        "event-timeout-kill",
+                        "worker-timeout-kill",
                         /* force_reset = */ true);
 }
 
+static Event* worker_detach_event(Worker *worker) {
+        assert(worker);
+
+        Event *event = TAKE_PTR(worker->event);
+        if (event)
+                assert_se(TAKE_PTR(event->worker) == worker);
+
+        if (worker->state != WORKER_KILLED)
+                worker->state = WORKER_IDLE;
+
+        (void) event_source_disable(worker->timeout_warning_event_source);
+        (void) event_source_disable(worker->timeout_kill_event_source);
+
+        return event;
+}
+
 static int worker_spawn(Manager *manager, Event *event) {
         int r;
 
@@ -757,9 +770,6 @@ static void event_requeue(Event *event) {
 
         sd_device *dev = ASSERT_PTR(event->dev);
 
-        event->timeout_warning_event = sd_event_source_disable_unref(event->timeout_warning_event);
-        event->timeout_event = sd_event_source_disable_unref(event->timeout_event);
-
         /* add a short delay to suppress busy loop */
         r = sd_event_now(event->manager->event, CLOCK_BOOTTIME, &now_usec);
         if (r < 0) {
@@ -802,10 +812,6 @@ static void event_requeue(Event *event) {
                 goto fail;
         }
 
-        if (event->worker)
-                event->worker->event = NULL;
-        event->worker = NULL;
-
         event->state = EVENT_QUEUED;
         return;
 
@@ -1152,15 +1158,13 @@ static int on_worker_notify(sd_event_source *s, int fd, uint32_t revents, void *
                 return 0;
         }
 
+        Event *event = worker_detach_event(worker);
+
         if (strv_contains(l, "TRY_AGAIN=1"))
                 /* Worker cannot lock the device. Requeue the event. */
-                event_requeue(worker->event);
+                event_requeue(event);
         else
-                event_free(worker->event);
-
-        /* Update the state of the worker. */
-        if (worker->state != WORKER_KILLED)
-                worker->state = WORKER_IDLE;
+                event_free(event);
 
         return 0;
 }