Skip to content

Commit

Permalink
manager: Add deferred parsing of mountinfo
Browse files Browse the repository at this point in the history
Manager start (measured via readiness notification) takes time that is
proportionate to number of entries in /proc/self/mountinfo since all
mount units must be enumerated.

This is problematic for user instances because:
a) they can start at times when lots of entries are created already,
b) their start latency propagates directly to user sessions
   establishment via pam_systemd.

Alleviate this latency by postponing full mountinfo parsing after the
manager notifies its readiness. The reasoning is that mount units that
are somehow relevant during startup of the user instance are referenced
by other units and they would be loaded on demand anyway. The complete
set of all mounts can be loaded later.

Use 'post' event source (instead of 'defer') since there is no point in
checking readiness in event loop when no other event was processed.

If a mount happens concurrently to the startup (mountinfo event),
manager will parse it completely, that is life. Fortunately,
user-runtime-dir@.service is ordered before user@.service startup so it
is safe from self-notifications.

Rough measurements with 3000 mount units:
> time systemctl start user@1000
before
        real	0m1.358s
        user	0m0.005s
        sys	0m0.013s

after
        real	0m0.351s
        user	0m0.008s
        sys	0m0.010s
  • Loading branch information
Werkov committed Oct 31, 2023
1 parent 553a596 commit a603be2
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/core/manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ struct Manager {
/* Data specific to the mount subsystem */
struct libmnt_monitor *mount_monitor;
sd_event_source *mount_event_source;
sd_event_source *mount_enumerate_source;

/* Data specific to the swap filesystem */
FILE *proc_swaps;
Expand Down
40 changes: 37 additions & 3 deletions src/core/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,22 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
return 0;
}

static int mount_enumerate_defer(sd_event_source *s, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
int r;

if (!m->ready_sent)
return 0;

r = mount_load_proc_self_mountinfo((Manager *)userdata, false);
if (r < 0)
return log_error_errno(r, "Failed to load mountinfo: %m");
r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
if (r < 0)
return log_error_errno(r, "Failed to disabled defered event source: %m");
return r;
}

static void mount_shutdown(Manager *m) {
assert(m);

Expand Down Expand Up @@ -2078,11 +2094,29 @@ static void mount_enumerate(Manager *m) {
}

(void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");

r = sd_event_add_post(m->event, &m->mount_enumerate_source, mount_enumerate_defer, m);
if (r < 0) {
log_error_errno(r, "Failed to add deferred mount enumerate source: %m");
goto fail;
}

r = sd_event_source_set_priority(m->mount_enumerate_source, SD_EVENT_PRIORITY_IDLE);
if (r < 0) {
log_error_errno(r, "Failed to adjust mount enumerate priority: %m");
goto fail;
}

}

r = mount_load_proc_self_mountinfo(m, false);
if (r < 0)
goto fail;
if (MANAGER_IS_SYSTEM(m)) {
r = mount_load_proc_self_mountinfo(m, false);
if (r < 0)
goto fail;
r = sd_event_source_set_enabled(m->mount_enumerate_source, SD_EVENT_OFF);
if (r < 0)
log_error_errno(r, "Failed to disable deferred mount enumerate source: %m");
}

return;

Expand Down

0 comments on commit a603be2

Please sign in to comment.