chiark / gitweb /
unit: add new abstracted maintenance state for units
[elogind.git] / src / mount.c
index ec03a52f6a7c4442d3f29e4893040dd769624797..f0336163ace7ffa7f885f58553f2503b6d597938 100644 (file)
@@ -35,6 +35,7 @@
 #include "unit-name.h"
 #include "mount.h"
 #include "dbus-mount.h"
+#include "special.h"
 
 static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_DEAD] = UNIT_INACTIVE,
@@ -49,7 +50,7 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_REMOUNTING_SIGKILL] = UNIT_ACTIVE_RELOADING,
         [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
         [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
-        [MOUNT_MAINTAINANCE] = UNIT_INACTIVE,
+        [MOUNT_MAINTENANCE] = UNIT_INACTIVE_MAINTENANCE
 };
 
 static void mount_init(Unit *u) {
@@ -167,6 +168,19 @@ static int mount_add_swap_links(Mount *m) {
         return 0;
 }
 
+static int mount_add_path_links(Mount *m) {
+        Meta *other;
+        int r;
+
+        assert(m);
+
+        LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_PATH])
+                if ((r = path_add_one_mount_link((Path*) other, m)) < 0)
+                        return r;
+
+        return 0;
+}
+
 static int mount_add_automount_links(Mount *m) {
         Meta *other;
         int r;
@@ -215,7 +229,7 @@ static int mount_add_target_links(Mount *m) {
         MountParameters *p;
         Unit *tu;
         int r;
-        bool noauto, handle, automount;
+        bool noauto, handle, automount, user;
 
         assert(m);
 
@@ -227,6 +241,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");
         handle = !!mount_test_option(p->options, "comment=systemd.mount");
         automount = !!mount_test_option(p->options, "comment=systemd.automount");
 
@@ -236,10 +251,10 @@ static int mount_add_target_links(Mount *m) {
         else
                 target = SPECIAL_LOCAL_FS_TARGET;
 
-        if ((r = manager_load_unit(UNIT(m)->meta.manager, target, NULL, &tu)) < 0)
+        if ((r = manager_load_unit(m->meta.manager, target, NULL, &tu)) < 0)
                 return r;
 
-        if (automount) {
+        if (automount && m->meta.manager->running_as == MANAGER_SYSTEM) {
                 Unit *am;
 
                 if ((r = unit_load_related_unit(UNIT(m), ".automount", &am)) < 0)
@@ -253,8 +268,9 @@ static int mount_add_target_links(Mount *m) {
         } else {
 
                 if (!noauto && handle)
-                        if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
-                                return r;
+                        if (user || 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);
         }
@@ -265,9 +281,12 @@ static int mount_verify(Mount *m) {
         char *e;
         assert(m);
 
-        if (UNIT(m)->meta.load_state != UNIT_LOADED)
+        if (m->meta.load_state != UNIT_LOADED)
                 return 0;
 
+        if (!m->from_etc_fstab && !m->from_fragment && !m->from_proc_self_mountinfo)
+                return -ENOENT;
+
         if (!(e = unit_name_from_path(m->where, ".mount")))
                 return -ENOMEM;
 
@@ -275,15 +294,20 @@ static int mount_verify(Mount *m) {
         free(e);
 
         if (!b) {
-                log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(m)->meta.id);
+                log_error("%s's Where setting doesn't match unit name. Refusing.", m->meta.id);
                 return -EINVAL;
         }
 
         if (m->meta.fragment_path && !m->parameters_fragment.what) {
-                log_error("%s's What setting is missing. Refusing.", UNIT(m)->meta.id);
+                log_error("%s's What setting is missing. Refusing.", m->meta.id);
                 return -EBADMSG;
         }
 
+        if (m->exec_context.pam_name && m->kill_mode != KILL_CONTROL_GROUP) {
+                log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", m->meta.id);
+                return -EINVAL;
+        }
+
         return 0;
 }
 
@@ -322,9 +346,7 @@ static int mount_load(Unit *u) {
                         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)
+                        if ((r = unit_add_node_link(u, what, u->meta.manager->running_as == MANAGER_SYSTEM)) < 0)
                                 return r;
 
                 if ((r = mount_add_mount_links(m)) < 0)
@@ -336,6 +358,9 @@ static int mount_load(Unit *u) {
                 if ((r = mount_add_swap_links(m)) < 0)
                         return r;
 
+                if ((r = mount_add_path_links(m)) < 0)
+                        return r;
+
                 if ((r = mount_add_automount_links(m)) < 0)
                         return r;
 
@@ -395,12 +420,12 @@ static void mount_set_state(Mount *m, MountState state) {
                  state == MOUNT_REMOUNTING_SIGKILL ||
                  state == MOUNT_UNMOUNTING_SIGTERM ||
                  state == MOUNT_UNMOUNTING_SIGKILL ||
-                 state == MOUNT_MAINTAINANCE)
+                 state == MOUNT_MAINTENANCE)
                 mount_notify_automount(m, -ENODEV);
 
         if (state != old_state)
                 log_debug("%s changed %s -> %s",
-                          UNIT(m)->meta.id,
+                          m->meta.id,
                           mount_state_to_string(old_state),
                           mount_state_to_string(state));
 
@@ -485,8 +510,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
 
         if (m->control_pid > 0)
                 fprintf(f,
-                        "%sControl PID: %llu\n",
-                        prefix, (unsigned long long) m->control_pid);
+                        "%sControl PID: %lu\n",
+                        prefix, (unsigned long) m->control_pid);
 
         exec_context_dump(&m->exec_context, f, prefix);
 }
@@ -509,8 +534,8 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
                             m->meta.manager->environment,
                             true,
                             true,
-                            UNIT(m)->meta.manager->confirm_spawn,
-                            UNIT(m)->meta.cgroup_bondings,
+                            m->meta.manager->confirm_spawn,
+                            m->meta.cgroup_bondings,
                             &pid)) < 0)
                 goto fail;
 
@@ -534,7 +559,7 @@ static void mount_enter_dead(Mount *m, bool success) {
         if (!success)
                 m->failure = true;
 
-        mount_set_state(m, m->failure ? MOUNT_MAINTAINANCE : MOUNT_DEAD);
+        mount_set_state(m, m->failure ? MOUNT_MAINTENANCE : MOUNT_DEAD);
 }
 
 static void mount_enter_mounted(Mount *m, bool success) {
@@ -562,7 +587,7 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
 
                 if (m->kill_mode == KILL_CONTROL_GROUP) {
 
-                        if ((r = cgroup_bonding_kill_list(UNIT(m)->meta.cgroup_bondings, sig)) < 0) {
+                        if ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig)) < 0) {
                                 if (r != -EAGAIN && r != -ESRCH)
                                         goto fail;
                         } else
@@ -589,7 +614,7 @@ static void mount_enter_signal(Mount *m, MountState state, bool success) {
         return;
 
 fail:
-        log_warning("%s failed to kill processes: %s", UNIT(m)->meta.id, strerror(-r));
+        log_warning("%s failed to kill processes: %s", m->meta.id, strerror(-r));
 
         if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
                 mount_enter_mounted(m, false);
@@ -625,7 +650,7 @@ static void mount_enter_unmounting(Mount *m, bool success) {
         return;
 
 fail:
-        log_warning("%s failed to run umount exectuable: %s", UNIT(m)->meta.id, strerror(-r));
+        log_warning("%s failed to run 'umount' task: %s", m->meta.id, strerror(-r));
         mount_enter_mounted(m, false);
 }
 
@@ -668,7 +693,7 @@ static void mount_enter_mounting(Mount *m) {
         return;
 
 fail:
-        log_warning("%s failed to run mount exectuable: %s", UNIT(m)->meta.id, strerror(-r));
+        log_warning("%s failed to run 'mount' task: %s", m->meta.id, strerror(-r));
         mount_enter_dead(m, false);
 }
 
@@ -759,7 +784,7 @@ static int mount_start(Unit *u) {
             m->state == MOUNT_MOUNTING_SIGKILL)
                 return 0;
 
-        assert(m->state == MOUNT_DEAD || m->state == MOUNT_MAINTAINANCE);
+        assert(m->state == MOUNT_DEAD || m->state == MOUNT_MAINTENANCE);
 
         m->failure = false;
         mount_enter_mounting(m);
@@ -818,7 +843,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
         unit_serialize_item(u, f, "failure", yes_no(m->failure));
 
         if (m->control_pid > 0)
-                unit_serialize_item_format(u, f, "control-pid", "%u", (unsigned) m->control_pid);
+                unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) m->control_pid);
 
         if (m->control_command_id >= 0)
                 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
@@ -851,12 +876,12 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
                         m->failure = b || m->failure;
 
         } else if (streq(key, "control-pid")) {
-                unsigned pid;
+                pid_t pid;
 
-                if ((r = safe_atou(value, &pid)) < 0 || pid <= 0)
+                if ((r = parse_pid(value, &pid)) < 0)
                         log_debug("Failed to parse control-pid value %s", value);
                 else
-                        m->control_pid = (pid_t) pid;
+                        m->control_pid = pid;
         } else if (streq(key, "control-command")) {
                 MountExecCommand id;
 
@@ -900,12 +925,14 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         assert(m);
         assert(pid >= 0);
 
-        success = is_clean_exit(code, status);
-        m->failure = m->failure || !success;
+        if (pid != m->control_pid)
+                return;
 
-        assert(m->control_pid == pid);
         m->control_pid = 0;
 
+        success = is_clean_exit(code, status);
+        m->failure = m->failure || !success;
+
         if (m->control_command) {
                 exec_status_fill(&m->control_command->exec_status, pid, code, status);
                 m->control_command = NULL;
@@ -931,7 +958,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         case MOUNT_REMOUNTING_SIGKILL:
         case MOUNT_REMOUNTING_SIGTERM:
 
-                if (success && m->from_proc_self_mountinfo)
+                if (success)
                         mount_enter_mounted(m, true);
                 else if (m->from_proc_self_mountinfo)
                         mount_enter_mounted(m, false);
@@ -1241,7 +1268,7 @@ finish:
 
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
         int r;
-        char *device, *path, *options, *fstype, *d, *p;
+        char *device, *path, *options, *options2, *fstype, *d, *p, *o;
 
         assert(m);
 
@@ -1250,7 +1277,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
         for (;;) {
                 int k;
 
-                device = path = options = fstype = d = p = NULL;
+                device = path = options = options2 = fstype = d = p = o = NULL;
 
                 if ((k = fscanf(m->proc_self_mountinfo,
                                 "%*s "       /* (1) mount id */
@@ -1263,11 +1290,13 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
                                 "- "         /* (8) seperator */
                                 "%ms "       /* (9) file system type */
                                 "%ms"        /* (10) mount source */
+                                "%ms"        /* (11) mount options 2 */
                                 "%*[^\n]",   /* some rubbish at the end */
                                 &path,
                                 &options,
                                 &fstype,
-                                &device)) != 4) {
+                                &device,
+                                &options2)) != 5) {
 
                         if (k == EOF)
                                 break;
@@ -1276,21 +1305,28 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
                         goto finish;
                 }
 
+                if (asprintf(&o, "%s,%s", options, options2) < 0) {
+                        r = -ENOMEM;
+                        goto finish;
+                }
+
                 if (!(d = cunescape(device)) ||
                     !(p = cunescape(path))) {
                         r = -ENOMEM;
                         goto finish;
                 }
 
-                if ((r = mount_add_one(m, d, p, options, fstype, true, set_flags)) < 0)
+                if ((r = mount_add_one(m, d, p, o, fstype, true, set_flags)) < 0)
                         goto finish;
 
                 free(device);
                 free(path);
                 free(options);
+                free(options2);
                 free(fstype);
                 free(d);
                 free(p);
+                free(o);
         }
 
         r = 0;
@@ -1299,9 +1335,11 @@ finish:
         free(device);
         free(path);
         free(options);
+        free(options2);
         free(fstype);
         free(d);
         free(p);
+        free(o);
 
         return r;
 }
@@ -1401,7 +1439,7 @@ void mount_fd_event(Manager *m, int events) {
                         switch (mount->state) {
 
                         case MOUNT_DEAD:
-                        case MOUNT_MAINTAINANCE:
+                        case MOUNT_MAINTENANCE:
                                 mount_enter_mounted(mount, true);
                                 break;
 
@@ -1489,7 +1527,7 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
         [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
         [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
         [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
-        [MOUNT_MAINTAINANCE] = "maintainance"
+        [MOUNT_MAINTENANCE] = "maintenance"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);