Merge pull request #986 from karelzak/monitor
mount: use libmount to monitor mountinfo & utab
This commit is contained in:
+2
-2
@@ -571,8 +571,8 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
|
||||
m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
|
||||
|
||||
m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd =
|
||||
m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd =
|
||||
m->cgroup_inotify_fd = -1;
|
||||
m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = -1;
|
||||
|
||||
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
|
||||
|
||||
m->ask_password_inotify_fd = -1;
|
||||
|
||||
+2
-3
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <libmount.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-event.h"
|
||||
@@ -176,10 +177,8 @@ struct Manager {
|
||||
Hashmap *devices_by_sysfs;
|
||||
|
||||
/* Data specific to the mount subsystem */
|
||||
FILE *proc_self_mountinfo;
|
||||
struct libmnt_monitor *mount_monitor;
|
||||
sd_event_source *mount_event_source;
|
||||
int utab_inotify_fd;
|
||||
sd_event_source *mount_utab_event_source;
|
||||
|
||||
/* Data specific to the swap filesystem */
|
||||
FILE *proc_swaps;
|
||||
|
||||
+43
-75
@@ -23,8 +23,6 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <signal.h>
|
||||
#include <libmount.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
#include "manager.h"
|
||||
#include "unit.h"
|
||||
@@ -1535,13 +1533,13 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
|
||||
}
|
||||
|
||||
static void mount_shutdown(Manager *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
m->mount_event_source = sd_event_source_unref(m->mount_event_source);
|
||||
m->mount_utab_event_source = sd_event_source_unref(m->mount_utab_event_source);
|
||||
|
||||
m->proc_self_mountinfo = safe_fclose(m->proc_self_mountinfo);
|
||||
m->utab_inotify_fd = safe_close(m->utab_inotify_fd);
|
||||
mnt_unref_monitor(m->mount_monitor);
|
||||
m->mount_monitor = NULL;
|
||||
}
|
||||
|
||||
static int mount_get_timeout(Unit *u, uint64_t *timeout) {
|
||||
@@ -1560,53 +1558,41 @@ static int mount_get_timeout(Unit *u, uint64_t *timeout) {
|
||||
|
||||
static int mount_enumerate(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
mnt_init_debug(0);
|
||||
|
||||
if (!m->proc_self_mountinfo) {
|
||||
m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
|
||||
if (!m->proc_self_mountinfo)
|
||||
return -errno;
|
||||
if (!m->mount_monitor) {
|
||||
int fd;
|
||||
|
||||
r = sd_event_add_io(m->event, &m->mount_event_source, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m);
|
||||
m->mount_monitor = mnt_new_monitor();
|
||||
if (!m->mount_monitor) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = mnt_monitor_enable_kernel(m->mount_monitor, 1);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
/* mnt_unref_monitor() will close the fd */
|
||||
fd = r = mnt_monitor_get_fd(m->mount_monitor);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = sd_event_add_io(m->event, &m->mount_event_source, fd, EPOLLIN, mount_dispatch_io, m);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
/* Dispatch this before we dispatch SIGCHLD, so that
|
||||
* we always get the events from /proc/self/mountinfo
|
||||
* before the SIGCHLD of /usr/bin/mount. */
|
||||
r = sd_event_source_set_priority(m->mount_event_source, -10);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) sd_event_source_set_description(m->mount_event_source, "mount-mountinfo-dispatch");
|
||||
}
|
||||
|
||||
if (m->utab_inotify_fd < 0) {
|
||||
m->utab_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
|
||||
if (m->utab_inotify_fd < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
(void) mkdir_p_label("/run/mount", 0755);
|
||||
|
||||
r = inotify_add_watch(m->utab_inotify_fd, "/run/mount", IN_MOVED_TO);
|
||||
if (r < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = sd_event_add_io(m->event, &m->mount_utab_event_source, m->utab_inotify_fd, EPOLLIN, mount_dispatch_io, m);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = sd_event_source_set_priority(m->mount_utab_event_source, -10);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) sd_event_source_set_description(m->mount_utab_event_source, "mount-utab-dispatch");
|
||||
(void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");
|
||||
}
|
||||
|
||||
r = mount_load_proc_self_mountinfo(m, false);
|
||||
@@ -1629,45 +1615,27 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(revents & (EPOLLPRI | EPOLLIN));
|
||||
assert(revents & EPOLLIN);
|
||||
|
||||
/* The manager calls this for every fd event happening on the
|
||||
* /proc/self/mountinfo file, which informs us about mounting
|
||||
* table changes, and for /run/mount events which we watch
|
||||
* for mount options. */
|
||||
|
||||
if (fd == m->utab_inotify_fd) {
|
||||
if (fd == mnt_monitor_get_fd(m->mount_monitor)) {
|
||||
bool rescan = false;
|
||||
|
||||
/* FIXME: We *really* need to replace this with
|
||||
* libmount's own API for this, we should not hardcode
|
||||
* internal behaviour of libmount here. */
|
||||
|
||||
for (;;) {
|
||||
union inotify_event_buffer buffer;
|
||||
struct inotify_event *e;
|
||||
ssize_t l;
|
||||
|
||||
l = read(fd, &buffer, sizeof(buffer));
|
||||
if (l < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
break;
|
||||
|
||||
log_error_errno(errno, "Failed to read utab inotify: %m");
|
||||
break;
|
||||
}
|
||||
|
||||
FOREACH_INOTIFY_EVENT(e, buffer, l) {
|
||||
/* Only care about changes to utab,
|
||||
* but we have to monitor the
|
||||
* directory to reliably get
|
||||
* notifications about when utab is
|
||||
* replaced using rename(2) */
|
||||
if ((e->mask & IN_Q_OVERFLOW) || streq(e->name, "utab"))
|
||||
rescan = true;
|
||||
}
|
||||
}
|
||||
/* Drain all events and verify that the event is valid.
|
||||
*
|
||||
* Note that libmount also monitors /run/mount mkdir if the
|
||||
* directory does not exist yet. The mkdir may generate event
|
||||
* which is irrelevant for us.
|
||||
*
|
||||
* error: r < 0; valid: r == 0, false positive: rc == 1 */
|
||||
do {
|
||||
r = mnt_monitor_next_change(m->mount_monitor, NULL, NULL);
|
||||
if (r == 0)
|
||||
rescan = true;
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to drain libmount events");
|
||||
} while (r == 0);
|
||||
|
||||
log_debug("libmount event [rescan: %s]", yes_no(rescan));
|
||||
if (!rescan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user