chiark / gitweb /
service: consider a process exiting with SIGTERM a clean exit
[elogind.git] / mount.c
diff --git a/mount.c b/mount.c
index 15cce6f8e442f64aa604042f5fe128605ae17300..ec03a52f6a7c4442d3f29e4893040dd769624797 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -113,95 +113,87 @@ static void mount_done(Unit *u) {
         unit_unwatch_timer(u, &m->timer_watch);
 }
 
-static int mount_add_node_links(Mount *m) {
-        Unit *device;
-        char *e;
+static int mount_add_mount_links(Mount *m) {
+        Meta *other;
         int r;
-        const char *what;
 
         assert(m);
 
-        /* Adds in links to the device that this node is based on */
+        /* Adds in links to other mount points that might lie below or
+         * above us in the hierarchy */
 
-        if (m->parameters_fragment.what)
-                what = m->parameters_fragment.what;
-        else if (m->parameters_etc_fstab.what)
-                what = m->parameters_etc_fstab.what;
-        else
-                /* We observe kernel mounts only while they are live,
-                 * hence don't create any links for them */
-                return 0;
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_MOUNT]) {
+                Mount *n = (Mount*) other;
 
-        if (!path_startswith(what, "/dev/"))
-                return 0;
+                if (n == m)
+                        continue;
 
-        if (!(e = unit_name_build_escape(what+1, NULL, ".device")))
-                return -ENOMEM;
+                if (n->meta.load_state != UNIT_LOADED)
+                        continue;
 
-        r = manager_load_unit(UNIT(m)->meta.manager, e, NULL, &device);
-        free(e);
+                if (path_startswith(m->where, n->where)) {
 
-        if (r < 0)
-                return r;
+                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
+                                return r;
 
-        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, device, true)) < 0)
-                return r;
+                        if (n->from_etc_fstab || n->from_fragment)
+                                if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
+                                        return r;
 
-        if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, device, true)) < 0)
-                return r;
+                } else if (path_startswith(n->where, m->where)) {
 
-        if (UNIT(m)->meta.manager->running_as == MANAGER_INIT ||
-            UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM)
-                if ((r = unit_add_dependency(device, UNIT_WANTS, UNIT(m), false)) < 0)
-                        return r;
+                        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(n), true)) < 0)
+                                return r;
+
+                        if (m->from_etc_fstab || m->from_fragment)
+                                if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                                        return r;
+                }
+        }
 
         return 0;
 }
 
-static int mount_add_path_links(Mount *m) {
+static int mount_add_swap_links(Mount *m) {
         Meta *other;
         int r;
 
         assert(m);
 
-        /* Adds in link to other mount points, that might lie below or
-         * above us in the hierarchy */
-
-        LIST_FOREACH(units_per_type, other, UNIT(m)->meta.manager->units_per_type[UNIT_MOUNT]) {
-                Mount *n;
-
-                n = (Mount*) other;
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_SWAP])
+                if ((r = swap_add_one_mount_link((Swap*) other, m)) < 0)
+                        return r;
 
-                if (n == m)
-                        continue;
+        return 0;
+}
 
-                if (m->meta.load_state != UNIT_LOADED)
-                        continue;
+static int mount_add_automount_links(Mount *m) {
+        Meta *other;
+        int r;
 
-                if (path_startswith(m->where, n->where)) {
+        assert(m);
 
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(other), true)) < 0)
-                                return r;
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_AUTOMOUNT])
+                if ((r = automount_add_one_mount_link((Automount*) other, m)) < 0)
+                        return r;
 
-                        if (n->from_etc_fstab || n->from_fragment)
-                                if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(other), true)) < 0)
-                                        return r;
+        return 0;
+}
 
-                } else if (path_startswith(n->where, m->where)) {
+static int mount_add_socket_links(Mount *m) {
+        Meta *other;
+        int r;
 
-                        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(other), true)) < 0)
-                                return r;
+        assert(m);
 
-                        if (m->from_etc_fstab || m->from_fragment)
-                                if ((r = unit_add_dependency(UNIT(other), UNIT_REQUIRES, UNIT(m), true)) < 0)
-                                        return r;
-                }
-        }
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_SOCKET])
+                if ((r = socket_add_one_mount_link((Socket*) other, m)) < 0)
+                        return r;
 
         return 0;
 }
 
-static bool mount_test_option(const char *haystack, const char *needle) {
+static char* mount_test_option(const char *haystack, const char *needle) {
         struct mntent me;
 
         assert(needle);
@@ -215,7 +207,7 @@ static bool mount_test_option(const char *haystack, const char *needle) {
         zero(me);
         me.mnt_opts = (char*) haystack;
 
-        return !!hasmntopt(&me, needle);
+        return hasmntopt(&me, needle);
 }
 
 static int mount_add_target_links(Mount *m) {
@@ -234,12 +226,9 @@ static int mount_add_target_links(Mount *m) {
         else
                 return 0;
 
-        noauto = mount_test_option(p->options, MNTOPT_NOAUTO);
-        handle = mount_test_option(p->options, "comment=systemd.mount");
-        automount = mount_test_option(p->options, "comment=systemd.automount");
-
-        if (noauto && !handle && !automount)
-                return 0;
+        noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
+        handle = !!mount_test_option(p->options, "comment=systemd.mount");
+        automount = !!mount_test_option(p->options, "comment=systemd.automount");
 
         if (mount_test_option(p->options, "_netdev") ||
             fstype_is_network(p->fstype))
@@ -263,7 +252,7 @@ static int mount_add_target_links(Mount *m) {
 
         } else {
 
-                if (handle)
+                if (!noauto && handle)
                         if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
                                 return r;
 
@@ -290,6 +279,11 @@ static int mount_verify(Mount *m) {
                 return -EINVAL;
         }
 
+        if (m->meta.fragment_path && !m->parameters_fragment.what) {
+                log_error("%s's What setting is missing. Refusing.", UNIT(m)->meta.id);
+                return -EBADMSG;
+        }
+
         return 0;
 }
 
@@ -305,6 +299,10 @@ static int mount_load(Unit *u) {
 
         /* This is a new unit? Then let's add in some extras */
         if (u->meta.load_state == UNIT_LOADED) {
+                const char *what = NULL;
+
+                if (m->meta.fragment_path)
+                        m->from_fragment = true;
 
                 if (!m->where)
                         if (!(m->where = unit_name_to_path(u->meta.id)))
@@ -312,20 +310,36 @@ static int mount_load(Unit *u) {
 
                 path_kill_slashes(m->where);
 
-                /* Minor validity checking */
-                if ((m->parameters_fragment.options || m->parameters_fragment.fstype) && !m->parameters_fragment.what)
-                        return -EBADMSG;
+                if (!m->meta.description)
+                        if ((r = unit_set_description(u, m->where)) < 0)
+                                return r;
 
-                if (m->parameters_fragment.what)
-                        m->from_fragment = true;
+                if (m->from_fragment && m->parameters_fragment.what)
+                        what = m->parameters_fragment.what;
+                else if (m->from_etc_fstab && m->parameters_etc_fstab.what)
+                        what = m->parameters_etc_fstab.what;
+                else if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
+                        what = m->parameters_proc_self_mountinfo.what;
+
+                if (what)
+                        if ((r = unit_add_node_link(u, what,
+                                                    (u->meta.manager->running_as == MANAGER_INIT ||
+                                                     u->meta.manager->running_as == MANAGER_SYSTEM))) < 0)
+                                return r;
 
-                if ((r = mount_add_node_links(MOUNT(u))) < 0)
+                if ((r = mount_add_mount_links(m)) < 0)
                         return r;
 
-                if ((r = mount_add_path_links(MOUNT(u))) < 0)
+                if ((r = mount_add_socket_links(m)) < 0)
                         return r;
 
-                if ((r = mount_add_target_links(MOUNT(u))) < 0)
+                if ((r = mount_add_swap_links(m)) < 0)
+                        return r;
+
+                if ((r = mount_add_automount_links(m)) < 0)
+                        return r;
+
+                if ((r = mount_add_target_links(m)) < 0)
                         return r;
 
                 if ((r = unit_add_default_cgroup(u)) < 0)
@@ -385,7 +399,7 @@ static void mount_set_state(Mount *m, MountState state) {
                 mount_notify_automount(m, -ENODEV);
 
         if (state != old_state)
-                log_debug("%s changed %s  %s",
+                log_debug("%s changed %s -> %s",
                           UNIT(m)->meta.id,
                           mount_state_to_string(old_state),
                           mount_state_to_string(state));
@@ -492,6 +506,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
                             NULL,
                             &m->exec_context,
                             NULL, 0,
+                            m->meta.manager->environment,
                             true,
                             true,
                             UNIT(m)->meta.manager->confirm_spawn,
@@ -885,7 +900,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         assert(m);
         assert(pid >= 0);
 
-        success = code == CLD_EXITED && status == 0;
+        success = is_clean_exit(code, status);
         m->failure = m->failure || !success;
 
         assert(m->control_pid == pid);
@@ -1009,7 +1024,7 @@ static int mount_add_one(
         Unit *u;
         bool delete;
         char *e, *w = NULL, *o = NULL, *f = NULL;
-        MountParameters *mp;
+        MountParameters *p;
 
         assert(m);
         assert(what);
@@ -1027,8 +1042,8 @@ static int mount_add_one(
         if (streq(fstype, "autofs"))
                 return 0;
 
-        /* probably some kind of swap, which we don't cover for now */
-        if (where[0] != '/')
+        /* probably some kind of swap, ignore */
+        if (!is_path(where))
                 return 0;
 
         if (!(e = unit_name_from_path(where, ".mount")))
@@ -1049,12 +1064,9 @@ static int mount_add_one(
                         goto fail;
 
                 if (!(MOUNT(u)->where = strdup(where))) {
-                            r = -ENOMEM;
-                            goto fail;
-                    }
-
-                if ((r = unit_set_description(u, where)) < 0)
+                        r = -ENOMEM;
                         goto fail;
+                }
 
                 unit_add_to_load_queue(u);
         } else {
@@ -1070,30 +1082,28 @@ static int mount_add_one(
         }
 
         if (from_proc_self_mountinfo) {
-                mp = &MOUNT(u)->parameters_proc_self_mountinfo;
+                p = &MOUNT(u)->parameters_proc_self_mountinfo;
 
                 if (set_flags) {
                         MOUNT(u)->is_mounted = true;
                         MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
-                        MOUNT(u)->just_changed = !streq_ptr(MOUNT(u)->parameters_proc_self_mountinfo.options, o);
+                        MOUNT(u)->just_changed = !streq_ptr(p->options, o);
                 }
 
                 MOUNT(u)->from_proc_self_mountinfo = true;
-
         } else {
-                mp = &MOUNT(u)->parameters_etc_fstab;
-
+                p = &MOUNT(u)->parameters_etc_fstab;
                 MOUNT(u)->from_etc_fstab = true;
         }
 
-        free(mp->what);
-        mp->what = w;
+        free(p->what);
+        p->what = w;
 
-        free(mp->options);
-        mp->options = o;
+        free(p->options);
+        p->options = o;
 
-        free(mp->fstype);
-        mp->fstype = f;
+        free(p->fstype);
+        p->fstype = f;
 
         unit_add_to_dbus_queue(u);
 
@@ -1107,7 +1117,7 @@ fail:
         if (delete && u)
                 unit_free(u);
 
-        return 0;
+        return r;
 }
 
 static char *fstab_node_to_udev_node(char *p) {
@@ -1148,6 +1158,27 @@ static char *fstab_node_to_udev_node(char *p) {
         return strdup(p);
 }
 
+static int mount_find_pri(char *options) {
+        char *end, *pri;
+        unsigned long r;
+
+        if (!(pri = mount_test_option(options, "pri=")))
+                return 0;
+
+        pri += 4;
+
+        errno = 0;
+        r = strtoul(pri, &end, 10);
+
+        if (errno != 0)
+                return -errno;
+
+        if (end == pri || (*end != ',' && *end != 0))
+                return -EINVAL;
+
+        return (int) r;
+}
+
 static int mount_load_etc_fstab(Manager *m) {
         FILE *f;
         int r;
@@ -1179,7 +1210,21 @@ static int mount_load_etc_fstab(Manager *m) {
                 if (where[0] == '/')
                         path_kill_slashes(where);
 
-                r = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, false, false);
+                if (streq(me->mnt_type, "swap")) {
+                        int pri;
+
+                        if ((pri = mount_find_pri(me->mnt_opts)) < 0)
+                                r = pri;
+                        else
+                                r = swap_add_one(m,
+                                                 what,
+                                                 pri,
+                                                 !!mount_test_option(me->mnt_opts, MNTOPT_NOAUTO),
+                                                 !!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
+                                                 false);
+                } else
+                        r = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, false, false);
+
                 free(what);
                 free(where);
 
@@ -1315,7 +1360,7 @@ void mount_fd_event(Manager *m, int events) {
          * table changes */
 
         if ((r = mount_load_proc_self_mountinfo(m, true)) < 0) {
-                log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-errno));
+                log_error("Failed to reread /proc/self/mountinfo: %s", strerror(errno));
 
                 /* Reset flags, just in case, for later calls */
                 LIST_FOREACH(units_per_type, meta, m->units_per_type[UNIT_MOUNT]) {
@@ -1462,6 +1507,7 @@ const UnitVTable mount_vtable = {
 
         .no_alias = true,
         .no_instances = true,
+        .no_isolate = true,
 
         .init = mount_init,
         .load = mount_load,