Skip to content

Commit e7ddaf3

Browse files
authored
udev: Make Storage Tests Stable Again ! (systemd#37262)
2 parents 7dcbb48 + 905a89a commit e7ddaf3

File tree

4 files changed

+107
-35
lines changed

4 files changed

+107
-35
lines changed

src/udev/udev-manager-ctrl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ int manager_start_ctrl(Manager *manager) {
125125
/* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
126126
* after fully processing the pending uevents (including the synthetic ones we may create due to
127127
* inotify events). */
128-
r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE);
128+
r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), EVENT_PRIORITY_CONTROL);
129129
if (r < 0)
130130
return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
131131

src/udev/udev-manager.c

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static int manager_reset_kill_workers_timer(Manager *manager) {
219219
USEC_PER_SEC,
220220
on_kill_workers_event,
221221
manager,
222-
SD_EVENT_PRIORITY_NORMAL,
222+
EVENT_PRIORITY_WORKER_TIMER,
223223
"kill-workers-event",
224224
/* force_reset = */ false);
225225
if (r < 0)
@@ -450,13 +450,28 @@ static void worker_attach_event(Worker *worker, Event *event) {
450450
event->state = EVENT_RUNNING;
451451
event->worker = worker;
452452

453-
(void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
454-
udev_warn_timeout(manager->config.timeout_usec), USEC_PER_SEC,
455-
on_event_timeout_warning, event);
456-
457-
(void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
458-
manager_kill_worker_timeout(manager), USEC_PER_SEC,
459-
on_event_timeout, event);
453+
(void) event_reset_time_relative(
454+
e,
455+
&event->timeout_warning_event,
456+
CLOCK_MONOTONIC,
457+
udev_warn_timeout(manager->config.timeout_usec),
458+
USEC_PER_SEC,
459+
on_event_timeout_warning,
460+
event,
461+
EVENT_PRIORITY_WORKER_TIMER,
462+
"event-timeout-warn",
463+
/* force_reset = */ true);
464+
465+
(void) event_reset_time_relative(
466+
e,
467+
&event->timeout_event, CLOCK_MONOTONIC,
468+
manager_kill_worker_timeout(manager),
469+
USEC_PER_SEC,
470+
on_event_timeout,
471+
event,
472+
EVENT_PRIORITY_WORKER_TIMER,
473+
"event-timeout-kill",
474+
/* force_reset = */ true);
460475
}
461476

462477
static int worker_spawn(Manager *manager, Event *event) {
@@ -740,10 +755,17 @@ static void event_requeue(Event *event) {
740755
if (event->retry_again_timeout_usec == 0)
741756
event->retry_again_timeout_usec = usec_add(now_usec, EVENT_RETRY_TIMEOUT_USEC);
742757

743-
r = event_reset_time_relative(event->manager->event, &event->retry_event_source,
744-
CLOCK_MONOTONIC, EVENT_RETRY_INTERVAL_USEC, 0,
745-
on_event_retry, NULL,
746-
0, "retry-event", true);
758+
r = event_reset_time_relative(
759+
event->manager->event,
760+
&event->retry_event_source,
761+
CLOCK_MONOTONIC,
762+
EVENT_RETRY_INTERVAL_USEC,
763+
/* accuracy = */ 0,
764+
on_event_retry,
765+
/* userdata = */ NULL,
766+
EVENT_PRIORITY_RETRY_EVENT,
767+
"retry-event",
768+
/* force_reset = */ true);
747769
if (r < 0) {
748770
log_device_warning_errno(
749771
dev, r,
@@ -852,16 +874,17 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
852874
.state = EVENT_QUEUED,
853875
};
854876

855-
if (!manager->events) {
877+
LIST_APPEND(event, manager->events, event);
878+
log_device_uevent(dev, "Device is queued");
879+
880+
if (!manager->queue_file_created) {
856881
r = touch("/run/udev/queue");
857882
if (r < 0)
858883
log_warning_errno(r, "Failed to touch /run/udev/queue, ignoring: %m");
884+
else
885+
manager->queue_file_created = true;
859886
}
860887

861-
LIST_APPEND(event, manager->events, event);
862-
863-
log_device_uevent(dev, "Device is queued");
864-
865888
return 0;
866889
}
867890

@@ -1153,15 +1176,17 @@ static int manager_unlink_queue_file(Manager *manager) {
11531176
if (manager->events)
11541177
return 0; /* There are queued events. */
11551178

1179+
if (!set_isempty(manager->synthesize_change_child_event_sources))
1180+
return 0; /* There are child processes that should trigger synthetic events. */
1181+
11561182
/* There are no queued events. Let's remove /run/udev/queue and clean up the idle processes. */
11571183
if (unlink("/run/udev/queue") < 0) {
1158-
if (errno == ENOENT)
1159-
return 0;
1160-
1161-
return log_warning_errno(errno, "Failed to unlink /run/udev/queue: %m");
1162-
}
1184+
if (errno != ENOENT)
1185+
return log_warning_errno(errno, "Failed to unlink /run/udev/queue: %m");
1186+
} else
1187+
log_debug("No events are queued, removed /run/udev/queue.");
11631188

1164-
log_debug("No events are queued, removed /run/udev/queue.");
1189+
manager->queue_file_created = false;
11651190
return 0;
11661191
}
11671192

@@ -1213,6 +1238,37 @@ static int on_post(sd_event_source *s, void *userdata) {
12131238
return 0;
12141239
}
12151240

1241+
static int manager_setup_signal(
1242+
Manager *manager,
1243+
sd_event *event,
1244+
int signal,
1245+
sd_event_signal_handler_t handler,
1246+
int64_t priority,
1247+
const char *description) {
1248+
1249+
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
1250+
int r;
1251+
1252+
assert(manager);
1253+
assert(event);
1254+
1255+
r = sd_event_add_signal(event, &s, signal | SD_EVENT_SIGNAL_PROCMASK, handler, manager);
1256+
if (r < 0)
1257+
return r;
1258+
1259+
r = sd_event_source_set_priority(s, priority);
1260+
if (r < 0)
1261+
return r;
1262+
1263+
(void) sd_event_source_set_description(s, description);
1264+
1265+
r = sd_event_source_set_floating(s, true);
1266+
if (r < 0)
1267+
return r;
1268+
1269+
return 0;
1270+
}
1271+
12161272
static int manager_setup_event(Manager *manager) {
12171273
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
12181274
int r;
@@ -1226,15 +1282,15 @@ static int manager_setup_event(Manager *manager) {
12261282
if (r < 0)
12271283
return log_error_errno(r, "Failed to allocate event loop: %m");
12281284

1229-
r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
1285+
r = manager_setup_signal(manager, e, SIGINT, on_sigterm, EVENT_PRIORITY_SIGTERM, "sigint-event-source");
12301286
if (r < 0)
12311287
return log_error_errno(r, "Failed to create SIGINT event source: %m");
12321288

1233-
r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, on_sigterm, manager);
1289+
r = manager_setup_signal(manager, e, SIGTERM, on_sigterm, EVENT_PRIORITY_SIGTERM, "sigterm-event-source");
12341290
if (r < 0)
12351291
return log_error_errno(r, "Failed to create SIGTERM event source: %m");
12361292

1237-
r = sd_event_add_signal(e, /* ret_event_source = */ NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, on_sighup, manager);
1293+
r = manager_setup_signal(manager, e, SIGHUP, on_sighup, EVENT_PRIORITY_SIGHUP, "sighup-event-source");
12381294
if (r < 0)
12391295
return log_error_errno(r, "Failed to create SIGHUP event source: %m");
12401296

src/udev/udev-manager.h

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,32 @@
1515
#include "udev-ctrl.h"
1616
#include "udev-def.h"
1717

18+
/* This should have a higher priority than the device monitor and inotify watch, to make device monitor and
19+
* inotify event source stopped as soon as possible when the signal is received. Otherwise, we may continue
20+
* receive events that needs to be serialized anyway. */
21+
#define EVENT_PRIORITY_SIGTERM (SD_EVENT_PRIORITY_NORMAL - 6)
22+
/* This must have a higher priority than the inotify event source, to make 'remove' uevent received earlier
23+
* than IN_IGNORED inotify event. */
24+
#define EVENT_PRIORITY_DEVICE_MONITOR (SD_EVENT_PRIORITY_NORMAL - 5)
1825
/* This must have a higher priority than the worker notification, to make IN_IGNORED event received earlier
1926
* than notifications about requests of adding/removing inotify watches. */
20-
#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 30)
27+
#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 4)
2128
/* This must have a higher priority than the worker SIGCHLD event, to make notifications about completions of
2229
* processing events received before SIGCHLD. */
23-
#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 20)
24-
/* This should have a higher priority than other events, especially timer events about killing long running
25-
* worker processes or idle worker processes. */
26-
#define EVENT_PRIORITY_WORKER_SIGCHLD (SD_EVENT_PRIORITY_NORMAL - 10)
27-
/* This should have a lower priority to make signal and timer event sources processed earlier. */
28-
#define EVENT_PRIORITY_DEVICE_MONITOR (SD_EVENT_PRIORITY_NORMAL + 10)
30+
#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 3)
31+
/* This should have a higher priority than timer events about killing long running worker processes or idle
32+
* worker processes. */
33+
#define EVENT_PRIORITY_WORKER_SIGCHLD (SD_EVENT_PRIORITY_NORMAL - 2)
34+
/* As said in the above, this should have a lower proority than the SIGCHLD event source. */
35+
#define EVENT_PRIORITY_WORKER_TIMER (SD_EVENT_PRIORITY_NORMAL - 1)
36+
/* This should have a lower priority than most event sources, but let's process earlier than varlink and the
37+
* legacy control socket. */
38+
#define EVENT_PRIORITY_SIGHUP (SD_EVENT_PRIORITY_NORMAL + 1)
39+
/* Let's not interrupt the service by any user process, even that requires privileges. */
40+
#define EVENT_PRIORITY_VARLINK (SD_EVENT_PRIORITY_NORMAL + 2)
41+
#define EVENT_PRIORITY_CONTROL (SD_EVENT_PRIORITY_NORMAL + 2)
42+
/* The event is intended to trigger the post-event source, hence can be the lowest priority. */
43+
#define EVENT_PRIORITY_RETRY_EVENT (SD_EVENT_PRIORITY_NORMAL + 3)
2944

3045
typedef struct Event Event;
3146
typedef struct UdevRules UdevRules;
@@ -61,6 +76,7 @@ typedef struct Manager {
6176
UdevConfig config_by_control;
6277
UdevConfig config;
6378

79+
bool queue_file_created;
6480
bool stop_exec_queue;
6581
bool exit;
6682
} Manager;

src/udev/udev-varlink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ int manager_start_varlink_server(Manager *manager) {
170170
/* This needs to be after the inotify and uevent handling, to make sure that the ping is send back
171171
* after fully processing the pending uevents (including the synthetic ones we may create due to
172172
* inotify events). */
173-
r = sd_varlink_server_attach_event(v, manager->event, SD_EVENT_PRIORITY_IDLE);
173+
r = sd_varlink_server_attach_event(v, manager->event, EVENT_PRIORITY_VARLINK);
174174
if (r < 0)
175175
return log_error_errno(r, "Failed to attach Varlink connection to event loop: %m");
176176

0 commit comments

Comments
 (0)