1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-04 09:18:12 +03:00

core/mount: process /proc/self/mountinfo at most once per sd-event iteration

This introduce a deferred event source that processes /proc/self/mountinfo,
and make the io event source triggered by libmount monitor not process the file,
but enable the deferred event source.
In this way, even if libmount monitor event source is triggered multiple
times within one sd-event iteration, mountinfo is parsed only once.

Hopefully, this improves system performance when the system is in a storm
of mount events.
This commit is contained in:
Yu Watanabe 2024-10-16 22:43:03 +09:00
parent 4ce436fccf
commit 03ada78295
2 changed files with 57 additions and 11 deletions

View File

@ -319,6 +319,7 @@ struct Manager {
/* Data specific to the mount subsystem */
struct libmnt_monitor *mount_monitor;
sd_event_source *mount_event_source;
sd_event_source *mount_defer_event_source;
/* Data specific to the swap filesystem */
FILE *proc_swaps;
@ -661,9 +662,10 @@ void unit_defaults_done(UnitDefaults *defaults);
enum {
/* most important … */
EVENT_PRIORITY_USER_LOOKUP = SD_EVENT_PRIORITY_NORMAL-11,
EVENT_PRIORITY_MOUNT_TABLE = SD_EVENT_PRIORITY_NORMAL-10,
EVENT_PRIORITY_SWAP_TABLE = SD_EVENT_PRIORITY_NORMAL-10,
EVENT_PRIORITY_USER_LOOKUP = SD_EVENT_PRIORITY_NORMAL-12,
EVENT_PRIORITY_SWAP_TABLE = SD_EVENT_PRIORITY_NORMAL-11,
EVENT_PRIORITY_MOUNT_TABLE = SD_EVENT_PRIORITY_NORMAL-11,
EVENT_PRIORITY_MOUNT_TABLE_DEFER = SD_EVENT_PRIORITY_NORMAL-10,
EVENT_PRIORITY_CGROUP_AGENT = SD_EVENT_PRIORITY_NORMAL-9, /* cgroupv1 */
EVENT_PRIORITY_CGROUP_INOTIFY = SD_EVENT_PRIORITY_NORMAL-9, /* cgroupv2 */
EVENT_PRIORITY_CGROUP_OOM = SD_EVENT_PRIORITY_NORMAL-8,

View File

@ -54,8 +54,10 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
[MOUNT_CLEANING] = UNIT_MAINTENANCE,
};
static int drain_libmount(Manager *m);
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int mount_dispatch_defer(sd_event_source *source, void *userdata);
static void mount_enter_dead(Mount *m, MountResult f, bool flush_result);
static void mount_enter_mounted(Mount *m, MountResult f);
static void mount_cycle_clear(Mount *m);
@ -1486,7 +1488,8 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
* race, let's explicitly scan /proc/self/mountinfo before we start processing /usr/bin/(u)mount
* dying. It's ugly, but it makes our ordering systematic again, and makes sure we always see
* /proc/self/mountinfo changes before our mount/umount exits. */
(void) mount_process_proc_self_mountinfo(u->manager);
if (drain_libmount(u->manager) > 0)
(void) mount_process_proc_self_mountinfo(u->manager);
pidref_done(&m->control_pid);
@ -1900,6 +1903,7 @@ static void mount_shutdown(Manager *m) {
assert(m);
m->mount_event_source = sd_event_source_disable_unref(m->mount_event_source);
m->mount_defer_event_source = sd_event_source_disable_unref(m->mount_defer_event_source);
mnt_unref_monitor(m->mount_monitor);
m->mount_monitor = NULL;
@ -2066,6 +2070,23 @@ static void mount_enumerate(Manager *m) {
}
(void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");
assert(!m->mount_defer_event_source);
r = sd_event_add_defer(m->event, &m->mount_defer_event_source, mount_dispatch_defer, m);
if (r < 0) {
log_error_errno(r, "Failed to add deferred event source for processing /proc/self/mountinfo: %m");
goto fail;
}
r = sd_event_source_set_priority(m->mount_defer_event_source, EVENT_PRIORITY_MOUNT_TABLE_DEFER);
if (r < 0) {
log_error_errno(r, "Failed to adjust priority of deferred event source for processing /proc/self/mountinfo: %m");
goto fail;
}
(void) sd_event_source_set_enabled(m->mount_defer_event_source, SD_EVENT_OFF);
(void) sd_event_source_set_description(m->mount_defer_event_source, "mount-monitor-dispatch-defer");
}
r = mount_load_proc_self_mountinfo(m, false);
@ -2108,10 +2129,6 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
assert(m);
r = drain_libmount(m);
if (r <= 0)
return r;
r = mount_load_proc_self_mountinfo(m, true);
if (r < 0) {
/* Reset flags, just in case, for later calls */
@ -2214,12 +2231,39 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
return 0;
}
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
static int mount_dispatch_defer(sd_event_source *s, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
assert(revents & EPOLLIN);
log_trace("Processing /proc/self/mountinfo by deferred event source.");
return mount_process_proc_self_mountinfo(m);
(void) drain_libmount(m);
(void) mount_process_proc_self_mountinfo(m);
return 0;
}
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
int r;
assert(revents & EPOLLIN);
assert(m->mount_defer_event_source);
r = drain_libmount(m);
if (r <= 0)
return r;
#if LOG_TRACE
if (sd_event_source_get_enabled(m->mount_defer_event_source, NULL) > 0)
log_trace("Deferred event source for processing /proc/self/mountinfo is already enabled.");
else
log_trace("Enabling deferred event source for processing /proc/self/mountinfo.");
#endif
r = sd_event_source_set_enabled(m->mount_defer_event_source, SD_EVENT_ONESHOT);
if (r < 0)
log_warning_errno(r, "Failed to enable event source for processing /proc/self/mountinfo: %m");
return 0;
}
static void mount_reset_failed(Unit *u) {