chiark / gitweb /
nspawn: bind mount /etc/localtime
[elogind.git] / src / mount.c
index 3fc0f1371657f689687e5029cf10f5905187e8d1..00780101a0c1edbced14f97a2ce6c0371416a33f 100644 (file)
@@ -36,6 +36,7 @@
 #include "dbus-mount.h"
 #include "special.h"
 #include "bus-errors.h"
+#include "exit-status.h"
 
 static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_DEAD] = UNIT_INACTIVE,
@@ -63,6 +64,7 @@ static void mount_init(Unit *u) {
         m->directory_mode = 0755;
 
         exec_context_init(&m->exec_context);
+        m->exec_context.std_output = EXEC_OUTPUT_KMSG;
 
         /* We need to make sure that /bin/mount is always called in
          * the same process group as us, so that the autofs kernel
@@ -97,12 +99,21 @@ static void mount_parameters_done(MountParameters *p) {
 
 static void mount_done(Unit *u) {
         Mount *m = MOUNT(u);
+        Meta *other;
 
         assert(m);
 
         free(m->where);
         m->where = NULL;
 
+        /* Try to detach us from the automount unit if there is any */
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_AUTOMOUNT]) {
+                Automount *a = (Automount*) other;
+
+                if (a->mount == m)
+                        a->mount = NULL;
+        }
+
         mount_parameters_done(&m->parameters_etc_fstab);
         mount_parameters_done(&m->parameters_proc_self_mountinfo);
         mount_parameters_done(&m->parameters_fragment);
@@ -265,7 +276,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);
 
@@ -277,10 +288,14 @@ 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");
-        handle = !!mount_test_option(p->options, "comment=systemd.mount") ||
+        nofail = !!mount_test_option(p->options, "nofail");
+        handle =
+                mount_test_option(p->options, "comment=systemd.mount") ||
+                mount_test_option(p->options, "x-systemd-mount") ||
                 m->meta.manager->mount_auto;
-        automount = !!mount_test_option(p->options, "comment=systemd.automount");
+        automount =
+                mount_test_option(p->options, "comment=systemd.automount") ||
+                mount_test_option(p->options, "x-systemd-automount");
 
         if (mount_test_option(p->options, "_netdev") ||
             (p->fstype && fstype_is_network(p->fstype))) {
@@ -295,7 +310,7 @@ static int mount_add_target_links(Mount *m) {
                 return r;
 
         if (after)
-                if ((r = unit_add_dependency_by_name(tu, UNIT_AFTER, after, NULL, true)) < 0)
+                if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true)) < 0)
                         return r;
 
         if (automount && m->meta.manager->running_as == MANAGER_SYSTEM) {
@@ -310,11 +325,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);
         }
@@ -361,6 +377,7 @@ static int mount_add_device_links(Mount *m) {
         }
 
         if (p->passno > 0 &&
+            !mount_is_bind(p) &&
             UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM &&
             !path_equal(m->where, "/")) {
                 char *name;
@@ -399,7 +416,7 @@ static int mount_add_default_dependencies(Mount *m) {
                 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;
         }
 
@@ -453,6 +470,9 @@ 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) {
+                if ((r = unit_add_exec_dependencies(u, &m->exec_context)) < 0)
+                        return r;
+
                 if (m->meta.fragment_path)
                         m->from_fragment = true;
 
@@ -487,7 +507,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)
@@ -553,7 +573,8 @@ static void mount_set_state(Mount *m, MountState state) {
                           mount_state_to_string(old_state),
                           mount_state_to_string(state));
 
-        unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state]);
+        unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], !m->reload_failure);
+        m->reload_failure = false;
 }
 
 static int mount_coldplug(Unit *u) {
@@ -712,9 +733,9 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
                            state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL;
 
                 if (m->control_pid > 0) {
-                        if (kill(m->exec_context.kill_mode == KILL_PROCESS_GROUP ?
-                                 -m->control_pid :
-                                 m->control_pid, sig) < 0 && errno != ESRCH)
+                        if (kill_and_sigcont(m->exec_context.kill_mode == KILL_PROCESS_GROUP ?
+                                             -m->control_pid :
+                                             m->control_pid, sig) < 0 && errno != ESRCH)
 
                                 log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
                         else
@@ -733,7 +754,7 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
                                 if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
                                         goto fail;
 
-                        if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig, pid_set)) < 0) {
+                        if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig, true, pid_set)) < 0) {
                                 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
                                         log_warning("Failed to kill control group: %s", strerror(-r));
                         } else if (r > 0)
@@ -909,7 +930,8 @@ static void mount_enter_remounting(Mount *m, bool success) {
 
 fail:
         log_warning("%s failed to run 'remount' task: %s", m->meta.id, strerror(-r));
-        mount_enter_mounted(m, false);
+        m->reload_failure = true;
+        mount_enter_mounted(m, true);
 }
 
 static int mount_start(Unit *u) {
@@ -1097,9 +1119,6 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         case MOUNT_MOUNTING_DONE:
         case MOUNT_MOUNTING_SIGKILL:
         case MOUNT_MOUNTING_SIGTERM:
-        case MOUNT_REMOUNTING:
-        case MOUNT_REMOUNTING_SIGKILL:
-        case MOUNT_REMOUNTING_SIGTERM:
 
                 if (success)
                         mount_enter_mounted(m, true);
@@ -1109,6 +1128,18 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                         mount_enter_dead(m, false);
                 break;
 
+        case MOUNT_REMOUNTING:
+        case MOUNT_REMOUNTING_SIGKILL:
+        case MOUNT_REMOUNTING_SIGTERM:
+
+                m->reload_failure = !success;
+                if (m->from_proc_self_mountinfo)
+                        mount_enter_mounted(m, true);
+                else
+                        mount_enter_dead(m, true);
+
+                break;
+
         case MOUNT_UNMOUNTING:
         case MOUNT_UNMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGTERM:
@@ -1146,7 +1177,8 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_REMOUNTING:
                 log_warning("%s remounting timed out. Stopping.", u->meta.id);
-                mount_enter_signal(m, MOUNT_REMOUNTING_SIGTERM, false);
+                m->reload_failure = true;
+                mount_enter_mounted(m, true);
                 break;
 
         case MOUNT_UNMOUNTING:
@@ -1155,18 +1187,45 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
                 break;
 
         case MOUNT_MOUNTING_SIGTERM:
-                log_warning("%s mounting timed out. Killing.", u->meta.id);
-                mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, false);
+                if (m->exec_context.send_sigkill) {
+                        log_warning("%s mounting timed out. Killing.", u->meta.id);
+                        mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, false);
+                } else {
+                        log_warning("%s mounting timed out. Skipping SIGKILL. Ignoring.", u->meta.id);
+
+                        if (m->from_proc_self_mountinfo)
+                                mount_enter_mounted(m, false);
+                        else
+                                mount_enter_dead(m, false);
+                }
                 break;
 
         case MOUNT_REMOUNTING_SIGTERM:
-                log_warning("%s remounting timed out. Killing.", u->meta.id);
-                mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, false);
+                if (m->exec_context.send_sigkill) {
+                        log_warning("%s remounting timed out. Killing.", u->meta.id);
+                        mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, false);
+                } else {
+                        log_warning("%s remounting timed out. Skipping SIGKILL. Ignoring.", u->meta.id);
+
+                        if (m->from_proc_self_mountinfo)
+                                mount_enter_mounted(m, false);
+                        else
+                                mount_enter_dead(m, false);
+                }
                 break;
 
         case MOUNT_UNMOUNTING_SIGTERM:
-                log_warning("%s unmounting timed out. Killing.", u->meta.id);
-                mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, false);
+                if (m->exec_context.send_sigkill) {
+                        log_warning("%s unmounting timed out. Killing.", u->meta.id);
+                        mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, false);
+                } else {
+                        log_warning("%s unmounting timed out. Skipping SIGKILL. Ignoring.", u->meta.id);
+
+                        if (m->from_proc_self_mountinfo)
+                                mount_enter_mounted(m, false);
+                        else
+                                mount_enter_dead(m, false);
+                }
                 break;
 
         case MOUNT_MOUNTING_SIGKILL:
@@ -1212,6 +1271,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;
@@ -1296,56 +1357,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;
@@ -1671,7 +1682,7 @@ static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
                                 goto finish;
                         }
 
-                if ((q = cgroup_bonding_kill_list(m->meta.cgroup_bondings, signo, pid_set)) < 0)
+                if ((q = cgroup_bonding_kill_list(m->meta.cgroup_bondings, signo, false, pid_set)) < 0)
                         if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
                                 r = q;
         }