[systemd-devel] [PATCH] mount: use libmount to monitor mountinfo & utab
Tom Gundersen
teg at jklm.no
Mon Jun 1 08:06:56 PDT 2015
Hi Karel,
On Mon, Jun 1, 2015 at 2:07 PM, Karel Zak <kzak at redhat.com> wrote:
> The current implementation directly monitor /proc/self/mountinfo and
> /run/mount/utab files. It's really not optimal because utab file is
> private libmount stuff without any official guaranteed semantic.
>
> The libmount since v2.26 provides API to monitor mount kernel &
> userspace changes. This patch replaces the current implementation with
> libmount based solution.
>
> Now the manager.h includes <libmount.h>, so $MOUNT_CFLAGS has been
> necessary to add to many tests CFLAGS.
>
> Note that mnt_monitor_event_cleanup() in v2.26 is broken, so the patch
> uses mnt_monitor_next_change(). It's exactly the same solution which
> uses the current libmount HEAD (mnt_monitor_event_cleanup() is API
> shorcut only).
Tiny nitpick below, otherwise look good to me.
Cheers,
Tom
> ---
> Makefile.am | 33 ++++++++++++------
> configure.ac | 2 +-
> src/core/manager.c | 2 +-
> src/core/manager.h | 5 ++-
> src/core/mount.c | 100 ++++++++++++-----------------------------------------
> 5 files changed, 49 insertions(+), 93 deletions(-)
>
> diff --git a/Makefile.am b/Makefile.am
> index ed5135d..3815e72 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1352,7 +1352,8 @@ systemd_SOURCES = \
>
> systemd_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> systemd_LDADD = \
> libsystemd-core.la \
> @@ -1554,7 +1555,8 @@ test_engine_SOURCES = \
>
> test_engine_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_engine_LDADD = \
> libsystemd-core.la \
> @@ -1565,7 +1567,8 @@ test_job_type_SOURCES = \
>
> test_job_type_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_job_type_LDADD = \
> libsystemd-core.la \
> @@ -1609,7 +1612,8 @@ test_unit_name_SOURCES = \
>
> test_unit_name_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_unit_name_LDADD = \
> libsystemd-core.la \
> @@ -1620,7 +1624,8 @@ test_unit_file_SOURCES = \
>
> test_unit_file_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_unit_file_LDADD = \
> libsystemd-core.la \
> @@ -1838,7 +1843,8 @@ test_tables_CPPFLAGS = \
>
> test_tables_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_tables_LDADD = \
> libsystemd-logs.la \
> @@ -1973,7 +1979,8 @@ test_cgroup_mask_SOURCES = \
> src/test/test-cgroup-mask.c
>
> test_cgroup_mask_CPPFLAGS = \
> - $(AM_CPPFLAGS)
> + $(AM_CPPFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_cgroup_mask_CFLAGS = \
> $(AM_CFLAGS) \
> @@ -2022,7 +2029,8 @@ test_path_SOURCES = \
> src/test/test-path.c
>
> test_path_CFLAGS = \
> - $(AM_CFLAGS)
> + $(AM_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_path_LDADD = \
> libsystemd-core.la
> @@ -2031,7 +2039,8 @@ test_execute_SOURCES = \
> src/test/test-execute.c
>
> test_execute_CFLAGS = \
> - $(AM_CFLAGS)
> + $(AM_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_execute_LDADD = \
> libsystemd-core.la
> @@ -2061,7 +2070,8 @@ test_sched_prio_SOURCES = \
> src/test/test-sched-prio.c
>
> test_sched_prio_CPPFLAGS = \
> - $(AM_CPPFLAGS)
> + $(AM_CPPFLAGS) \
> + $(MOUNT_CFLAGS)
>
> test_sched_prio_CFLAGS = \
> $(AM_CFLAGS) \
> @@ -2133,7 +2143,8 @@ systemd_analyze_SOURCES = \
>
> systemd_analyze_CFLAGS = \
> $(AM_CFLAGS) \
> - $(SECCOMP_CFLAGS)
> + $(SECCOMP_CFLAGS) \
> + $(MOUNT_CFLAGS)
>
> systemd_analyze_LDADD = \
> libsystemd-core.la \
> diff --git a/configure.ac b/configure.ac
> index 48cedb5..74ec386 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -454,7 +454,7 @@ AM_CONDITIONAL(HAVE_BLKID, [test "$have_blkid" = "yes"])
>
> # ------------------------------------------------------------------------------
> have_libmount=no
> -PKG_CHECK_MODULES(MOUNT, [ mount >= 2.20 ],
> +PKG_CHECK_MODULES(MOUNT, [ mount >= 2.26 ],
> [AC_DEFINE(HAVE_LIBMOUNT, 1, [Define if libmount is available]) have_libmount=yes], have_libmount=no)
> if test "x$have_libmount" = xno; then
> AC_MSG_ERROR([*** libmount support required but libraries not found])
> diff --git a/src/core/manager.c b/src/core/manager.c
> index b931b0d..6881bb2 100644
> --- a/src/core/manager.c
> +++ b/src/core/manager.c
> @@ -567,7 +567,7 @@ 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 = -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 = -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;
> diff --git a/src/core/manager.h b/src/core/manager.h
> index 4ef869d..5cd8884 100644
> --- a/src/core/manager.h
> +++ b/src/core/manager.h
> @@ -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;
> diff --git a/src/core/mount.c b/src/core/mount.c
> index ba1dcf1..3b6a519 100644
> --- a/src/core/mount.c
> +++ b/src/core/mount.c
> @@ -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"
> @@ -1539,16 +1537,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);
>
> - if (m->proc_self_mountinfo) {
> - fclose(m->proc_self_mountinfo);
> - m->proc_self_mountinfo = NULL;
> - }
> - 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) {
> @@ -1567,53 +1562,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);
> - if (r < 0)
> + m->mount_monitor = mnt_new_monitor();
> + if (!m->mount_monitor) {
> + r = -ENOMEM;
> 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)
> + r = mnt_monitor_enable_kernel(m->mount_monitor, 1);
> + if (r)
> 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;
> + r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL);
> + if (r)
> 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;
> + /* 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_utab_event_source, m->utab_inotify_fd, EPOLLIN, mount_dispatch_io, m);
> + r = sd_event_add_io(m->event, &m->mount_event_source, fd, EPOLLIN | EPOLLPRI, mount_dispatch_io, m);
> if (r < 0)
> goto fail;
>
> - r = sd_event_source_set_priority(m->mount_utab_event_source, -10);
> + r = sd_event_source_set_priority(m->mount_event_source, -10);
> if (r < 0)
> goto fail;
>
> - (void) sd_event_source_set_description(m->mount_utab_event_source, "mount-utab-dispatch");
> + sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");
This should be cast to (void) unless you check the return.
> }
>
> r = mount_load_proc_self_mountinfo(m, false);
> @@ -1638,46 +1621,9 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
> assert(m);
> assert(revents & (EPOLLPRI | 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) {
> - 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;
> - }
> - }
> -
> - if (!rescan)
> - return 0;
> - }
> + if (fd == mnt_monitor_get_fd(m->mount_monitor))
> + /* Drain all changes from the monitor */
> + while (mnt_monitor_next_change(m->mount_monitor, NULL, NULL) == 0);
>
> r = mount_load_proc_self_mountinfo(m, true);
> if (r < 0) {
> --
> 2.4.1
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
More information about the systemd-devel
mailing list