chiark / gitweb /
Rename more things to elogind
[elogind.git] / src / core / mount.c
index 13c634807b07672ea0b8eba1aa4a831958348b99..53594cd40b4379f3e5350e48824e53ac6f7ce74d 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <errno.h>
 #include <stdio.h>
-#include <mntent.h>
 #include <sys/epoll.h>
 #include <signal.h>
 #include <libmount.h>
@@ -30,8 +29,6 @@
 #include "manager.h"
 #include "unit.h"
 #include "mount.h"
-#include "load-fragment.h"
-#include "load-dropin.h"
 #include "log.h"
 #include "sd-messages.h"
 #include "strv.h"
@@ -41,9 +38,8 @@
 #include "unit-name.h"
 #include "dbus-mount.h"
 #include "special.h"
-#include "bus-common-errors.h"
 #include "exit-status.h"
-#include "def.h"
+#include "fstab-util.h"
 
 #define RETRY_UMOUNT_MAX 32
 
@@ -70,7 +66,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 
 static bool mount_needs_network(const char *options, const char *fstype) {
-        if (mount_test_option(options, "_netdev"))
+        if (fstab_test_option(options, "_netdev\0"))
                 return true;
 
         if (fstype && fstype_is_network(fstype))
@@ -88,16 +84,10 @@ static bool mount_is_network(const MountParameters *p) {
 static bool mount_is_bind(const MountParameters *p) {
         assert(p);
 
-        if (mount_test_option(p->options, "bind"))
+        if (fstab_test_option(p->options, "bind\0" "rbind\0"))
                 return true;
 
-        if (p->fstype && streq(p->fstype, "bind"))
-                return true;
-
-        if (mount_test_option(p->options, "rbind"))
-                return true;
-
-        if (p->fstype && streq(p->fstype, "rbind"))
+        if (p->fstype && STR_IN_SET(p->fstype, "bind", "rbind"))
                 return true;
 
         return false;
@@ -106,23 +96,22 @@ static bool mount_is_bind(const MountParameters *p) {
 static bool mount_is_auto(const MountParameters *p) {
         assert(p);
 
-        return !mount_test_option(p->options, "noauto");
+        return !fstab_test_option(p->options, "noauto\0");
 }
 
 static bool needs_quota(const MountParameters *p) {
         assert(p);
 
-        if (mount_is_network(p))
+        /* Quotas are not enabled on network filesystems,
+         * but we want them, for example, on storage connected via iscsi */
+        if (p->fstype && fstype_is_network(p->fstype))
                 return false;
 
         if (mount_is_bind(p))
                 return false;
 
-        return mount_test_option(p->options, "usrquota") ||
-                mount_test_option(p->options, "grpquota") ||
-                mount_test_option(p->options, "quota") ||
-                mount_test_option(p->options, "usrjquota") ||
-                mount_test_option(p->options, "grpjquota");
+        return fstab_test_option(p->options,
+                                 "usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0");
 }
 
 static void mount_init(Unit *u) {
@@ -308,7 +297,7 @@ static int mount_add_device_links(Mount *m) {
 
         assert(m);
 
-        p = get_mount_parameters_fragment(m);
+        p = get_mount_parameters(m);
         if (!p)
                 return 0;
 
@@ -369,7 +358,7 @@ static bool should_umount(Mount *m) {
                 return false;
 
         p = get_mount_parameters(m);
-        if (p && mount_test_option(p->options, "x-initrd.mount") &&
+        if (p && fstab_test_option(p->options, "x-initrd.mount\0") &&
             !in_initrd())
                 return false;
 
@@ -386,13 +375,20 @@ static int mount_add_default_dependencies(Mount *m) {
         if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
                 return 0;
 
-        p = get_mount_parameters(m);
-
-        if (!p)
+        /* We do not add any default dependencies to / and /usr, since
+         * they are guaranteed to stay mounted the whole time, since
+         * our system is on it. Also, don't bother with anything
+         * mounted below virtual file systems, it's also going to be
+         * virtual, and hence not worth the effort. */
+        if (path_equal(m->where, "/") ||
+            path_equal(m->where, "/usr") ||
+            path_startswith(m->where, "/proc") ||
+            path_startswith(m->where, "/sys") ||
+            path_startswith(m->where, "/dev"))
                 return 0;
 
-        if (path_equal(m->where, "/") ||
-            path_equal(m->where, "/usr"))
+        p = get_mount_parameters(m);
+        if (!p)
                 return 0;
 
         if (mount_is_network(p)) {
@@ -618,7 +614,7 @@ static void mount_set_state(Mount *m, MountState state) {
         m->reload_result = MOUNT_SUCCESS;
 }
 
-static int mount_coldplug(Unit *u) {
+static int mount_coldplug(Unit *u, Hashmap *deferred_work) {
         Mount *m = MOUNT(u);
         MountState new_state = MOUNT_DEAD;
         int r;
@@ -712,7 +708,11 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         assert(c);
         assert(_pid);
 
-        unit_realize_cgroup(UNIT(m));
+        (void) unit_realize_cgroup(UNIT(m));
+        if (m->reset_cpu_usage) {
+                (void) unit_reset_cpu_usage(UNIT(m));
+                m->reset_cpu_usage = false;
+        }
 
         r = unit_setup_exec_runtime(UNIT(m));
         if (r < 0)
@@ -925,6 +925,13 @@ static void mount_enter_mounting(Mount *m) {
                 goto fail;
 
         if (m->from_fragment) {
+                _cleanup_free_ char *opts = NULL;
+
+                r = fstab_filter_options(m->parameters_fragment.options,
+                                         "nofail\0" "noauto\0" "auto\0", NULL, NULL, &opts);
+                if (r < 0)
+                        goto fail;
+
                 r = exec_command_set(m->control_command, "/bin/mount",
                                      m->parameters_fragment.what, m->where, NULL);
                 if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
@@ -933,8 +940,8 @@ static void mount_enter_mounting(Mount *m) {
                         r = exec_command_append(m->control_command, "-s", NULL);
                 if (r >= 0 && m->parameters_fragment.fstype)
                         r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
-                if (r >= 0 && m->parameters_fragment.options)
-                        r = exec_command_append(m->control_command, "-o", m->parameters_fragment.options, NULL);
+                if (r >= 0 && !isempty(opts))
+                        r = exec_command_append(m->control_command, "-o", opts, NULL);
         } else
                 r = -ENOENT;
 
@@ -970,7 +977,7 @@ static void mount_enter_remounting(Mount *m) {
                 const char *o;
 
                 if (m->parameters_fragment.options)
-                        o = strappenda("remount,", m->parameters_fragment.options);
+                        o = strjoina("remount,", m->parameters_fragment.options);
                 else
                         o = "remount";
 
@@ -1029,9 +1036,10 @@ static int mount_start(Unit *u) {
 
         m->result = MOUNT_SUCCESS;
         m->reload_result = MOUNT_SUCCESS;
+        m->reset_cpu_usage = true;
 
         mount_enter_mounting(m);
-        return 0;
+        return 1;
 }
 
 static int mount_stop(Unit *u) {
@@ -1055,7 +1063,7 @@ static int mount_stop(Unit *u) {
                m->state == MOUNT_REMOUNTING_SIGKILL);
 
         mount_enter_unmounting(m);
-        return 0;
+        return 1;
 }
 
 static int mount_reload(Unit *u) {
@@ -1385,7 +1393,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
         return 0;
 }
 
-static int mount_add_one(
+static int mount_setup_unit(
                 Manager *m,
                 const char *what,
                 const char *where,
@@ -1428,7 +1436,7 @@ static int mount_add_one(
 
                 u = unit_new(m, sizeof(Mount));
                 if (!u)
-                        return -ENOMEM;
+                        return log_oom();
 
                 r = unit_add_name(u, e);
                 if (r < 0)
@@ -1541,6 +1549,8 @@ static int mount_add_one(
         return 0;
 
 fail:
+        log_warning_errno(r, "Failed to set up mount unit: %m");
+
         if (delete && u)
                 unit_free(u);
 
@@ -1548,33 +1558,36 @@ fail:
 }
 
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
-        _cleanup_(mnt_free_tablep) struct libmnt_table *tb = NULL;
-        _cleanup_(mnt_free_iterp) struct libmnt_iter *itr = NULL;
-        struct libmnt_fs *fs;
+        _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
+        _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
         int r = 0;
 
         assert(m);
 
-        tb = mnt_new_table();
-        itr = mnt_new_iter(MNT_ITER_FORWARD);
-        if (!tb || !itr)
+        t = mnt_new_table();
+        if (!t)
                 return log_oom();
 
-        r = mnt_table_parse_mtab(tb, NULL);
+        i = mnt_new_iter(MNT_ITER_FORWARD);
+        if (!i)
+                return log_oom();
+
+        r = mnt_table_parse_mtab(t, NULL);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
         r = 0;
         for (;;) {
                 const char *device, *path, *options, *fstype;
                 _cleanup_free_ const char *d = NULL, *p = NULL;
+                struct libmnt_fs *fs;
                 int k;
 
-                k = mnt_table_next_fs(tb, itr, &fs);
+                k = mnt_table_next_fs(t, i, &fs);
                 if (k == 1)
                         break;
-                else if (k < 0)
-                        return log_error_errno(k, "Failed to get next entry from /etc/fstab: %m");
+                if (k < 0)
+                        return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m");
 
                 device = mnt_fs_get_source(fs);
                 path = mnt_fs_get_target(fs);
@@ -1582,11 +1595,16 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
                 fstype = mnt_fs_get_fstype(fs);
 
                 d = cunescape(device);
+                if (!d)
+                        return log_oom();
+
                 p = cunescape(path);
-                if (!d || !p)
+                if (!p)
                         return log_oom();
 
-                k = mount_add_one(m, d, p, options, fstype, set_flags);
+                (void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags);
+
+                k = mount_setup_unit(m, d, p, options, fstype, set_flags);
                 if (r == 0 && k < 0)
                         r = k;
         }
@@ -1730,8 +1748,6 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
 
         r = mount_load_proc_self_mountinfo(m, true);
         if (r < 0) {
-                log_error_errno(r, "Failed to reread /proc/self/mountinfo: %m");
-
                 /* Reset flags, just in case, for later calls */
                 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
                         Mount *mount = MOUNT(u);
@@ -1764,6 +1780,10 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                                 break;
                         }
 
+                        if (mount->parameters_proc_self_mountinfo.what)
+                                (void) device_found_node(m, mount->parameters_proc_self_mountinfo.what, false, DEVICE_FOUND_MOUNT, true);
+
+
                 } else if (mount->just_mounted || mount->just_changed) {
 
                         /* New or changed mount entry */