chiark / gitweb /
cgroup: by default, duplicate service cgroup in the cpu hierarchy
[elogind.git] / src / mount.c
index 28ed8c3ddcbd1558025010dc22836d4bd99e3c56..077ab9160f848329304252e439bf11747a4fe203 100644 (file)
@@ -35,6 +35,7 @@
 #include "unit-name.h"
 #include "dbus-mount.h"
 #include "special.h"
+#include "bus-errors.h"
 
 static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_DEAD] = UNIT_INACTIVE,
@@ -264,7 +265,7 @@ static int mount_add_target_links(Mount *m) {
         MountParameters *p;
         Unit *tu;
         int r;
-        bool noauto, handle, automount, user;
+        bool noauto, nofail, handle, automount;
 
         assert(m);
 
@@ -276,7 +277,7 @@ static int mount_add_target_links(Mount *m) {
                 return 0;
 
         noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
-        user = mount_test_option(p->options, "user") || mount_test_option(p->options, "users");
+        nofail = !!mount_test_option(p->options, "nofail");
         handle = !!mount_test_option(p->options, "comment=systemd.mount") ||
                 m->meta.manager->mount_auto;
         automount = !!mount_test_option(p->options, "comment=systemd.automount");
@@ -309,11 +310,12 @@ static int mount_add_target_links(Mount *m) {
                 /* Automatically add mount points that aren't natively
                  * configured to local-fs.target */
                 if (!noauto &&
+                    !nofail &&
                     handle &&
-                    !m->from_fragment)
-                        if (user || m->meta.manager->running_as == MANAGER_SYSTEM)
-                                if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
-                                        return r;
+                    m->from_etc_fstab &&
+                    m->meta.manager->running_as == MANAGER_SYSTEM)
+                        if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
+                                return r;
 
                 return unit_add_dependency(UNIT(m), UNIT_BEFORE, tu, true);
         }
@@ -333,7 +335,7 @@ static bool mount_is_bind(MountParameters *p) {
 
 static int mount_add_device_links(Mount *m) {
         MountParameters *p;
-        bool nofail, noauto;
+        int r;
 
         assert(m);
 
@@ -344,18 +346,47 @@ static int mount_add_device_links(Mount *m) {
         else
                 return 0;
 
-        if (!p->what || path_equal(m->where, "/"))
+        if (!p->what)
                 return 0;
 
-        if (mount_is_bind(p))
-                return 0;
+        if (!mount_is_bind(p) && !path_equal(m->where, "/")) {
+                bool nofail, noauto;
 
-        noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
-        nofail = !!mount_test_option(p->options, "nofail");
+                noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
+                nofail = !!mount_test_option(p->options, "nofail");
+
+                if ((r = unit_add_node_link(UNIT(m), p->what,
+                                            !noauto && nofail &&
+                                            UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM)) < 0)
+                        return r;
+        }
 
-        return unit_add_node_link(UNIT(m), p->what,
-                                  !noauto && nofail &&
-                                  UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM);
+        if (p->passno > 0 &&
+            UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM &&
+            !path_equal(m->where, "/")) {
+                char *name;
+                Unit *fsck;
+                /* Let's add in the fsck service */
+
+                /* aka SPECIAL_FSCK_SERVICE */
+                if (!(name = unit_name_from_path_instance("fsck", p->what, ".service")))
+                        return -ENOMEM;
+
+                if ((r = manager_load_unit_prepare(m->meta.manager, name, NULL, NULL, &fsck)) < 0) {
+                        log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
+                        free(name);
+                        return r;
+                }
+
+                free(name);
+
+                SERVICE(fsck)->fsck_passno = p->passno;
+
+                if ((r = unit_add_two_dependencies(UNIT(m), UNIT_AFTER, UNIT_REQUIRES, fsck, true)) < 0)
+                        return r;
+        }
+
+        return 0;
 }
 
 static int mount_add_default_dependencies(Mount *m) {
@@ -366,10 +397,10 @@ static int mount_add_default_dependencies(Mount *m) {
         if (m->meta.manager->running_as == MANAGER_SYSTEM &&
             !path_equal(m->where, "/")) {
 
-                if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_FSCK_TARGET, NULL, true)) < 0)
+                if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, SPECIAL_QUOTACHECK_SERVICE, NULL, true)) < 0)
                         return r;
 
-                if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTED_BY, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
+                if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
                         return r;
         }
 
@@ -457,7 +488,7 @@ static int mount_load(Unit *u) {
                 if ((r = mount_add_target_links(m)) < 0)
                         return r;
 
-                if ((r = unit_add_default_cgroup(u)) < 0)
+                if ((r = unit_add_default_cgroups(u)) < 0)
                         return r;
 
                 if (m->meta.default_dependencies)
@@ -1161,6 +1192,7 @@ static int mount_add_one(
                 const char *where,
                 const char *options,
                 const char *fstype,
+                int passno,
                 bool from_proc_self_mountinfo,
                 bool set_flags) {
         int r;
@@ -1181,6 +1213,8 @@ static int mount_add_one(
          * dependencies ever. */
         if (mount_point_is_api(where))
                 return 0;
+        if (mount_point_ignore(where))
+                return 0;
 
         if (streq(fstype, "autofs"))
                 return 0;
@@ -1248,6 +1282,8 @@ static int mount_add_one(
         free(p->fstype);
         p->fstype = f;
 
+        p->passno = passno;
+
         unit_add_to_dbus_queue(u);
 
         return 0;
@@ -1263,56 +1299,6 @@ fail:
         return r;
 }
 
-static char *fstab_node_to_udev_node(char *p) {
-        char *dn, *t, *u;
-        int r;
-
-        /* FIXME: to follow udev's logic 100% we need to leave valid
-         * UTF8 chars unescaped */
-
-        if (startswith(p, "LABEL=")) {
-
-                if (!(u = unquote(p+6, "\"\'")))
-                        return NULL;
-
-                t = xescape(u, "/ ");
-                free(u);
-
-                if (!t)
-                        return NULL;
-
-                r = asprintf(&dn, "/dev/disk/by-label/%s", t);
-                free(t);
-
-                if (r < 0)
-                        return NULL;
-
-                return dn;
-        }
-
-        if (startswith(p, "UUID=")) {
-
-                if (!(u = unquote(p+5, "\"\'")))
-                        return NULL;
-
-                t = xescape(u, "/ ");
-                free(u);
-
-                if (!t)
-                        return NULL;
-
-                r = asprintf(&dn, "/dev/disk/by-uuid/%s", ascii_strlower(t));
-                free(t);
-
-                if (r < 0)
-                        return NULL;
-
-                return dn;
-        }
-
-        return strdup(p);
-}
-
 static int mount_find_pri(char *options) {
         char *end, *pri;
         unsigned long r;
@@ -1381,7 +1367,7 @@ static int mount_load_etc_fstab(Manager *m) {
                                                  !!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
                                                  false);
                 } else
-                        k = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, false, false);
+                        k = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, me->mnt_passno, false, false);
 
                 free(what);
                 free(where);
@@ -1447,7 +1433,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
                         goto finish;
                 }
 
-                if ((k = mount_add_one(m, d, p, o, fstype, true, set_flags)) < 0)
+                if ((k = mount_add_one(m, d, p, o, fstype, 0, true, set_flags)) < 0)
                         r = k;
 
 clean_up:
@@ -1496,7 +1482,7 @@ static int mount_enumerate(Manager *m) {
                 m->mount_watch.fd = fileno(m->proc_self_mountinfo);
 
                 zero(ev);
-                ev.events = EPOLLERR;
+                ev.events = EPOLLPRI;
                 ev.data.ptr = &m->mount_watch;
 
                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
@@ -1521,7 +1507,7 @@ void mount_fd_event(Manager *m, int events) {
         int r;
 
         assert(m);
-        assert(events == EPOLLERR);
+        assert(events & EPOLLPRI);
 
         /* The manager calls this for every fd event happening on the
          * /proc/self/mountinfo file, which informs us about mounting
@@ -1604,6 +1590,52 @@ static void mount_reset_failed(Unit *u) {
         m->failure = false;
 }
 
+static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) {
+        Mount *m = MOUNT(u);
+        int r = 0;
+        Set *pid_set = NULL;
+
+        assert(m);
+
+        if (who == KILL_MAIN) {
+                dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Mount units have no main processes");
+                return -EINVAL;
+        }
+
+        if (m->control_pid <= 0 && who == KILL_CONTROL) {
+                dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
+                return -ENOENT;
+        }
+
+        if (m->control_pid > 0)
+                if (kill(mode == KILL_PROCESS_GROUP ? -m->control_pid : m->control_pid, signo) < 0)
+                        r = -errno;
+
+        if (mode == KILL_CONTROL_GROUP) {
+                int q;
+
+                if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func)))
+                        return -ENOMEM;
+
+                /* Exclude the control pid from being killed via the cgroup */
+                if (m->control_pid > 0)
+                        if ((q = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0) {
+                                r = q;
+                                goto finish;
+                        }
+
+                if ((q = cgroup_bonding_kill_list(m->meta.cgroup_bondings, signo, pid_set)) < 0)
+                        if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
+                                r = q;
+        }
+
+finish:
+        if (pid_set)
+                set_free(pid_set);
+
+        return r;
+}
+
 static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
         [MOUNT_DEAD] = "dead",
         [MOUNT_MOUNTING] = "mounting",
@@ -1650,6 +1682,8 @@ const UnitVTable mount_vtable = {
         .stop = mount_stop,
         .reload = mount_reload,
 
+        .kill = mount_kill,
+
         .serialize = mount_serialize,
         .deserialize_item = mount_deserialize_item,