#include "strv.h"
#include "mount-setup.h"
#include "unit-name.h"
-#include "mount.h"
#include "dbus-mount.h"
#include "special.h"
static int mount_add_mount_links(Mount *m) {
Meta *other;
int r;
+ MountParameters *pm;
assert(m);
+ if (m->from_fragment)
+ pm = &m->parameters_fragment;
+ else if (m->from_etc_fstab)
+ pm = &m->parameters_etc_fstab;
+ else
+ pm = NULL;
+
/* Adds in links to other mount points that might lie below or
* above us in the hierarchy */
LIST_FOREACH(units_per_type, other, m->meta.manager->units_per_type[UNIT_MOUNT]) {
Mount *n = (Mount*) other;
+ MountParameters *pn;
if (n == m)
continue;
if (n->meta.load_state != UNIT_LOADED)
continue;
+ if (n->from_fragment)
+ pn = &n->parameters_fragment;
+ else if (n->from_etc_fstab)
+ pn = &n->parameters_etc_fstab;
+ else
+ pn = NULL;
+
if (path_startswith(m->where, n->where)) {
if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
} else if (path_startswith(n->where, m->where)) {
- if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(n), true)) < 0)
+ if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), 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;
+
+ } else if (pm && path_startswith(pm->what, n->where)) {
+
+ if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
+ return r;
+
+ if (m->from_etc_fstab || m->from_fragment)
+ if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
+ return r;
+
+ } else if (pn && path_startswith(pn->what, m->where)) {
+
+ if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
+ return r;
+
+ if (n->from_etc_fstab || n->from_fragment)
+ if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
+ return r;
}
}
}
static int mount_add_target_links(Mount *m) {
- const char *target;
+ const char *target, *after = NULL;
MountParameters *p;
Unit *tu;
int r;
automount = !!mount_test_option(p->options, "comment=systemd.automount");
if (mount_test_option(p->options, "_netdev") ||
- fstype_is_network(p->fstype))
+ fstype_is_network(p->fstype)) {
target = SPECIAL_REMOTE_FS_TARGET;
- else
+
+ if (m->meta.manager->running_as == MANAGER_SYSTEM)
+ after = SPECIAL_NETWORK_TARGET;
+ } else
target = SPECIAL_LOCAL_FS_TARGET;
if ((r = manager_load_unit(m->meta.manager, target, NULL, NULL, &tu)) < 0)
return r;
+ if (after)
+ if ((r = unit_add_dependency_by_name(tu, UNIT_AFTER, after, NULL, true)) < 0)
+ return r;
+
if (automount && m->meta.manager->running_as == MANAGER_SYSTEM) {
Unit *am;
}
}
+static bool mount_is_bind(MountParameters *p) {
+ assert(p);
+
+ if (p->fstype && streq(p->fstype, "bind"))
+ return true;
+
+ if (mount_test_option(p->options, "bind"))
+ return true;
+
+ return false;
+}
+
static int mount_add_device_links(Mount *m) {
MountParameters *p;
bool nofail, noauto;
if (!p->what || path_equal(m->where, "/"))
return 0;
+ if (mount_is_bind(p))
+ return 0;
+
noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
nofail = !!mount_test_option(p->options, "nofail");
static void mount_enter_signal(Mount *m, MountState state, bool success) {
int r;
- bool sent = false;
+ Set *pid_set = NULL;
+ bool wait_for_exit = false;
assert(m);
state == MOUNT_UNMOUNTING_SIGTERM ||
state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL;
- if (m->exec_context.kill_mode == KILL_CONTROL_GROUP) {
+ 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 ((r = cgroup_bonding_kill_list(m->meta.cgroup_bondings, sig)) < 0) {
- if (r != -EAGAIN && r != -ESRCH)
- goto fail;
- } else
- sent = true;
+ log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
+ else
+ wait_for_exit = true;
}
- if (!sent && m->control_pid > 0)
- if (kill(m->exec_context.kill_mode == KILL_PROCESS ?
- m->control_pid :
- -m->control_pid, sig) < 0 && errno != ESRCH) {
+ if (m->exec_context.kill_mode == KILL_CONTROL_GROUP) {
- r = -errno;
+ if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
+ r = -ENOMEM;
goto fail;
}
+
+ /* Exclude the control pid from being killed via the cgroup */
+ if (m->control_pid > 0)
+ 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 != -EAGAIN && r != -ESRCH && r != -ENOENT)
+ log_warning("Failed to kill control group: %s", strerror(-r));
+ } else if (r > 0)
+ wait_for_exit = true;
+
+ set_free(pid_set);
+ }
}
- if (sent) {
+ if (wait_for_exit) {
if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
goto fail;
mount_enter_mounted(m, false);
else
mount_enter_dead(m, false);
+
+ if (pid_set)
+ set_free(pid_set);
}
static void mount_enter_unmounting(Mount *m, bool success) {
if (startswith(p, "LABEL=")) {
- if (!(u = unquote(p+6, '"')))
+ if (!(u = unquote(p+6, "\"\'")))
return NULL;
t = xescape(u, "/ ");
if (startswith(p, "UUID=")) {
- if (!(u = unquote(p+5, '"')))
+ if (!(u = unquote(p+5, "\"\'")))
return NULL;
t = xescape(u, "/ ");