+ "%sWhere: %s\n"
+ "%sWhat: %s\n"
+ "%sFile System Type: %s\n"
+ "%sOptions: %s\n"
+ "%sFrom /etc/fstab: %s\n"
+ "%sFrom /proc/self/mountinfo: %s\n"
+ "%sFrom fragment: %s\n"
+ "%sKillMode: %s\n",
+ prefix, state_string_table[m->state],
+ prefix, m->where,
+ prefix, strna(p->what),
+ prefix, strna(p->fstype),
+ prefix, strna(p->options),
+ prefix, yes_no(m->from_etc_fstab),
+ prefix, yes_no(m->from_proc_self_mountinfo),
+ prefix, yes_no(m->from_fragment),
+ prefix, kill_mode_to_string(m->kill_mode));
+
+ if (m->control_pid > 0)
+ fprintf(f,
+ "%sControl PID: %llu\n",
+ prefix, (unsigned long long) m->control_pid);
+
+ exec_context_dump(&m->exec_context, f, prefix);
+}
+
+static void mount_enter_dead(Mount *m, bool success) {
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ mount_set_state(m, m->failure ? MOUNT_MAINTAINANCE : MOUNT_DEAD);
+}
+
+static void mount_enter_signal(Mount *m, MountState state, bool success) {
+ int r;
+
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ if (m->control_pid > 0) {
+ int sig;
+ bool sent = false;
+
+ sig = (state == MOUNT_MOUNTING_SIGTERM ||
+ state == MOUNT_UNMOUNTING_SIGTERM ||
+ state == MOUNT_REMOUNTING_SIGTERM) ? SIGTERM : SIGKILL;
+
+ if (m->kill_mode == KILL_CONTROL_GROUP) {
+
+ if ((r = cgroup_bonding_kill_list(UNIT(m)->meta.cgroup_bondings, sig)) < 0) {
+ if (r != -EAGAIN && r != -ESRCH)
+ goto fail;
+ } else
+ sent = true;
+ }
+
+ if (!sent)
+ if (kill(m->kill_mode == KILL_PROCESS ? m->control_pid : -m->control_pid, sig) < 0 && errno != ESRCH) {
+ r = -errno;
+ goto fail;
+ }
+ }
+
+ mount_set_state(m, state);
+
+ if (m->control_pid <= 0)
+ mount_enter_dead(m, true);
+
+ return;
+
+fail:
+ log_warning("%s failed to kill processes: %s", unit_id(UNIT(m)), strerror(-r));
+ mount_enter_dead(m, false);
+}
+
+static void mount_enter_mounted(Mount *m, bool success) {
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ mount_set_state(m, MOUNT_MOUNTED);
+}
+
+static void mount_enter_unmounting(Mount *m, bool success) {
+ ExecCommand *c;
+ int r;
+
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ m->control_command = c = m->exec_command + MOUNT_EXEC_UNMOUNT;
+
+ if ((r = exec_command_set(
+ c,
+ "/bin/umount",
+ m->where,
+ NULL)) < 0)
+ goto fail;
+
+ service_unwatch_control_pid(m);
+
+ if ((r = mount_spawn(m, c, &m->control_pid)) < 0)
+ goto fail;
+
+ mount_set_state(m, MOUNT_UNMOUNTING);
+
+ return;
+
+fail:
+ log_warning("%s failed to run umount exectuable: %s", unit_id(UNIT(m)), strerror(-r));
+ mount_enter_mounted(m, false);
+}
+
+static void mount_enter_mounting(Mount *m, bool success) {
+ ExecCommand *c;
+ int r;
+
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ m->control_command = c = m->exec_command + MOUNT_EXEC_MOUNT;
+
+ if (m->from_fragment)
+ r = exec_command_set(
+ c,
+ "/bin/mount",
+ m->parameters_fragment.what,
+ m->where,
+ "-t", m->parameters_fragment.fstype,
+ "-o", m->parameters_fragment.options,
+ NULL);
+ else if (m->from_etc_fstab)
+ r = exec_command_set(
+ c,
+ "/bin/mount",
+ m->where,
+ NULL);
+ else
+ r = -ENOENT;
+
+ if (r < 0)
+ goto fail;
+
+ service_unwatch_control_pid(m);
+
+ if ((r = mount_spawn(m, c, &m->control_pid)) < 0)
+ goto fail;
+
+ mount_set_state(m, MOUNT_MOUNTING);
+
+ return;
+
+fail:
+ log_warning("%s failed to run mount exectuable: %s", unit_id(UNIT(m)), strerror(-r));
+ mount_enter_dead(m, false);
+}
+
+static void mount_enter_mounting_done(Mount *m, bool success) {
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ mount_set_state(m, MOUNT_MOUNTING_DONE);
+}
+
+static void mount_enter_remounting(Mount *m, bool success) {
+ ExecCommand *c;
+ int r;
+
+ assert(m);
+
+ if (!success)
+ m->failure = true;
+
+ m->control_command = c = m->exec_command + MOUNT_EXEC_REMOUNT;
+
+ if (m->from_fragment) {
+ char *buf = NULL;
+ const char *o;
+
+ if (m->parameters_fragment.options) {
+ if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ o = buf;
+ } else
+ o = "remount";
+
+ r = exec_command_set(
+ c,
+ "/bin/mount",
+ m->parameters_fragment.what,
+ m->where,
+ "-t", m->parameters_fragment.fstype,
+ "-o", o,
+ NULL);
+
+ free(buf);
+ } else if (m->from_etc_fstab)
+ r = exec_command_set(
+ c,
+ "/bin/mount",
+ m->where,
+ "-o", "remount",
+ NULL);
+ else
+ r = -ENOENT;
+
+ if (r < 0) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ service_unwatch_control_pid(m);
+
+ if ((r = mount_spawn(m, c, &m->control_pid)) < 0)
+ goto fail;
+
+ mount_set_state(m, MOUNT_REMOUNTING);
+
+ return;
+
+fail:
+ mount_enter_mounted(m, false);
+}
+
+static int mount_start(Unit *u) {
+ Mount *m = MOUNT(u);
+
+ assert(m);
+
+ /* We cannot fulfill this request right now, try again later
+ * please! */
+ if (m->state == MOUNT_UNMOUNTING ||
+ m->state == MOUNT_UNMOUNTING_SIGTERM ||
+ m->state == MOUNT_UNMOUNTING_SIGKILL)
+ return -EAGAIN;
+
+ /* Already on it! */
+ if (m->state == MOUNT_MOUNTING ||
+ m->state == MOUNT_MOUNTING_SIGTERM ||
+ m->state == MOUNT_MOUNTING_SIGKILL)
+ return 0;
+
+ assert(m->state == MOUNT_DEAD || m->state == MOUNT_MAINTAINANCE);
+
+ m->failure = false;
+
+ mount_enter_mounting(m, true);
+ return 0;
+}
+
+static int mount_stop(Unit *u) {
+ Mount *m = MOUNT(u);
+
+ assert(m);
+
+ /* Cann't do this right now. */
+ if (m->state == MOUNT_MOUNTING ||
+ m->state == MOUNT_MOUNTING_DONE ||
+ m->state == MOUNT_MOUNTING_SIGTERM ||
+ m->state == MOUNT_MOUNTING_SIGKILL ||
+ m->state == MOUNT_REMOUNTING ||
+ m->state == MOUNT_REMOUNTING_SIGTERM ||
+ m->state == MOUNT_REMOUNTING_SIGKILL)
+ return -EAGAIN;
+
+ /* Already on it */
+ if (m->state == MOUNT_UNMOUNTING ||
+ m->state == MOUNT_UNMOUNTING_SIGKILL ||
+ m->state == MOUNT_UNMOUNTING_SIGTERM)
+ return 0;
+
+ assert(m->state == MOUNT_MOUNTED);
+
+ mount_enter_unmounting(m, true);
+ return 0;
+}
+
+static int mount_reload(Unit *u) {
+ Mount *m = MOUNT(u);
+
+ assert(m);
+
+ if (m->state == MOUNT_MOUNTING_DONE)
+ return -EAGAIN;
+
+ assert(m->state == MOUNT_MOUNTED);
+
+ mount_enter_remounting(m, true);
+ return 0;