-/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
[MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
[MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
[MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
- [MOUNT_MAINTENANCE] = UNIT_MAINTENANCE
+ [MOUNT_FAILED] = UNIT_FAILED
};
static void mount_init(Unit *u) {
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");
+ handle = !!mount_test_option(p->options, "comment=systemd.mount") ||
+ m->meta.manager->mount_auto;
automount = !!mount_test_option(p->options, "comment=systemd.automount");
if (mount_test_option(p->options, "_netdev") ||
return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_WANTS, UNIT(am), true);
} else {
- if (!noauto && handle)
+ /* Automatically add mount points that aren't natively
+ * configured to local-fs.target */
+ if (!noauto &&
+ 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;
}
}
+static int mount_add_device_links(Mount *m) {
+ MountParameters *p;
+ bool nofail, noauto;
+
+ assert(m);
+
+ if (m->from_fragment)
+ p = &m->parameters_fragment;
+ else if (m->from_etc_fstab)
+ p = &m->parameters_etc_fstab;
+ else
+ return 0;
+
+ if (!p->what || path_equal(m->where, "/"))
+ return 0;
+
+ noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
+ nofail = !!mount_test_option(p->options, "nofail");
+
+ return unit_add_node_link(UNIT(m), p->what,
+ !noauto && nofail &&
+ UNIT(m)->meta.manager->running_as == MANAGER_SYSTEM);
+}
+
static int mount_add_default_dependencies(Mount *m) {
int r;
assert(m);
- if (m->meta.manager->running_as == MANAGER_SYSTEM) {
+ if (m->meta.manager->running_as == MANAGER_SYSTEM &&
+ !path_equal(m->where, "/")) {
- if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SYSINIT_TARGET, NULL, true)) < 0)
+ if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_FSCK_TARGET, NULL, true)) < 0)
return r;
- if (!path_equal(m->where, "/"))
- if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, 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)
+ return r;
}
return 0;
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_SYSTEM)) < 0)
- return r;
+ if ((r = mount_add_device_links(m)) < 0)
+ return r;
if ((r = mount_add_mount_links(m)) < 0)
return r;
state == MOUNT_REMOUNTING_SIGKILL ||
state == MOUNT_UNMOUNTING_SIGTERM ||
state == MOUNT_UNMOUNTING_SIGKILL ||
- state == MOUNT_MAINTENANCE)
+ state == MOUNT_FAILED)
mount_notify_automount(m, -ENODEV);
if (state != old_state)
if (!success)
m->failure = true;
- mount_set_state(m, m->failure ? MOUNT_MAINTENANCE : MOUNT_DEAD);
+ mount_set_state(m, m->failure ? MOUNT_FAILED : MOUNT_DEAD);
}
static void mount_enter_mounted(Mount *m, bool success) {
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) {
return;
fail:
+ log_warning("%s failed to run 'remount' task: %s", m->meta.id, strerror(-r));
mount_enter_mounted(m, false);
}
m->state == MOUNT_MOUNTING_SIGKILL)
return 0;
- assert(m->state == MOUNT_DEAD || m->state == MOUNT_MAINTENANCE);
+ assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
m->failure = false;
mount_enter_mounting(m);
static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Mount *m = MOUNT(u);
- int r;
assert(u);
assert(key);
} else if (streq(key, "control-pid")) {
pid_t pid;
- if ((r = parse_pid(value, &pid)) < 0)
+ if (parse_pid(value, &pid) < 0)
log_debug("Failed to parse control-pid value %s", value);
else
m->control_pid = pid;
default:
assert_not_reached("Uh, control process died at wrong time.");
}
+
+ /* Notify clients about changed exit status */
+ unit_add_to_dbus_queue(u);
}
static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
}
static char *fstab_node_to_udev_node(char *p) {
- char *dn, *t;
+ char *dn, *t, *u;
int r;
/* FIXME: to follow udev's logic 100% we need to leave valid
if (startswith(p, "LABEL=")) {
- if (!(t = xescape(p+6, "/ ")))
+ 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);
if (startswith(p, "UUID=")) {
- if (!(t = xescape(p+5, "/ ")))
+ 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));
what,
pri,
!!mount_test_option(me->mnt_opts, MNTOPT_NOAUTO),
+ !!mount_test_option(me->mnt_opts, "nofail"),
!!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
false);
} else
* 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(-r));
/* Reset flags, just in case, for later calls */
LIST_FOREACH(units_per_type, meta, m->units_per_type[UNIT_MOUNT]) {
switch (mount->state) {
case MOUNT_DEAD:
- case MOUNT_MAINTENANCE:
+ case MOUNT_FAILED:
mount_enter_mounted(mount, true);
break;
}
}
-int mount_path_is_mounted(Manager *m, const char* path) {
- char *t;
- int r;
-
- assert(m);
- assert(path);
-
- if (path[0] != '/')
- return 1;
-
- if (!(t = strdup(path)))
- return -ENOMEM;
-
- path_kill_slashes(t);
-
- for (;;) {
- char *e, *slash;
- Unit *u;
-
- if (!(e = unit_name_from_path(t, ".mount"))) {
- r = -ENOMEM;
- goto finish;
- }
-
- u = manager_get_unit(m, e);
- free(e);
-
- if (u &&
- (MOUNT(u)->from_etc_fstab || MOUNT(u)->from_fragment) &&
- MOUNT(u)->state != MOUNT_MOUNTED) {
- r = 0;
- goto finish;
- }
-
- assert_se(slash = strrchr(t, '/'));
-
- if (slash == t) {
- r = 1;
- goto finish;
- }
-
- *slash = 0;
- }
-
- r = 1;
-
-finish:
- free(t);
- return r;
-}
-
-static void mount_reset_maintenance(Unit *u) {
+static void mount_reset_failed(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
- if (m->state == MOUNT_MAINTENANCE)
+ if (m->state == MOUNT_FAILED)
mount_set_state(m, MOUNT_DEAD);
m->failure = false;
[MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
[MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
[MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
- [MOUNT_MAINTENANCE] = "maintenance"
+ [MOUNT_FAILED] = "failed"
};
DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
.sigchld_event = mount_sigchld_event,
.timer_event = mount_timer_event,
- .reset_maintenance = mount_reset_maintenance,
+ .reset_failed = mount_reset_failed,
+ .bus_interface = "org.freedesktop.systemd1.Mount",
.bus_message_handler = bus_mount_message_handler,
+ .bus_invalidating_properties = bus_mount_invalidating_properties,
.enumerate = mount_enumerate,
.shutdown = mount_shutdown