[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