Systemd/src/core/mount.c

2021 lines
64 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <signal.h>
2010-01-29 02:07:41 +01:00
#include <stdio.h>
2010-01-29 06:04:08 +01:00
#include <sys/epoll.h>
#include <libmount.h>
#include "sd-messages.h"
#include "alloc-util.h"
2010-04-18 03:08:16 +02:00
#include "dbus-mount.h"
#include "device.h"
#include "escape.h"
#include "exit-status.h"
#include "format-util.h"
#include "fstab-util.h"
#include "log.h"
#include "manager.h"
#include "mkdir.h"
#include "mount-setup.h"
#include "mount-util.h"
#include "mount.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "serialize.h"
#include "special.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
#include "unit.h"
#define RETRY_UMOUNT_MAX 32
2014-11-28 23:04:24 +01:00
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
2010-01-29 03:18:09 +01:00
static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = UNIT_INACTIVE,
[MOUNT_MOUNTING] = UNIT_ACTIVATING,
[MOUNT_MOUNTING_DONE] = UNIT_ACTIVATING,
2010-01-29 03:18:09 +01:00
[MOUNT_MOUNTED] = UNIT_ACTIVE,
[MOUNT_REMOUNTING] = UNIT_RELOADING,
2010-01-29 03:18:09 +01:00
[MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
[MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
[MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
[MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
[MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
[MOUNT_FAILED] = UNIT_FAILED
2010-01-29 03:18:09 +01:00
};
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
return IN_SET(state,
MOUNT_MOUNTING,
MOUNT_MOUNTING_DONE,
MOUNT_REMOUNTING,
MOUNT_REMOUNTING_SIGTERM,
MOUNT_REMOUNTING_SIGKILL,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
MOUNT_UNMOUNTING_SIGKILL);
}
static bool mount_needs_network(const char *options, const char *fstype) {
if (fstab_test_option(options, "_netdev\0"))
return true;
if (fstype && fstype_is_network(fstype))
return true;
return false;
}
2014-11-28 20:22:47 +01:00
static bool mount_is_network(const MountParameters *p) {
assert(p);
return mount_needs_network(p->options, p->fstype);
}
static bool mount_is_loop(const MountParameters *p) {
assert(p);
if (fstab_test_option(p->options, "loop\0"))
return true;
return false;
}
2014-11-28 20:22:47 +01:00
static bool mount_is_bind(const MountParameters *p) {
assert(p);
if (fstab_test_option(p->options, "bind\0" "rbind\0"))
return true;
if (p->fstype && STR_IN_SET(p->fstype, "bind", "rbind"))
return true;
return false;
}
2014-11-28 20:22:47 +01:00
static bool mount_is_auto(const MountParameters *p) {
assert(p);
return !fstab_test_option(p->options, "noauto\0");
}
static bool mount_is_automount(const MountParameters *p) {
assert(p);
return fstab_test_option(p->options,
"comment=systemd.automount\0"
"x-systemd.automount\0");
}
static bool mount_is_bound_to_device(const Mount *m) {
const MountParameters *p;
if (m->from_fragment)
return true;
p = &m->parameters_proc_self_mountinfo;
return fstab_test_option(p->options, "x-systemd.device-bound\0");
}
2014-11-28 20:22:47 +01:00
static bool needs_quota(const MountParameters *p) {
assert(p);
/* Quotas are not enabled on network filesystems,
2015-04-01 13:08:25 +02:00
* but we want them, for example, on storage connected via iscsi */
if (p->fstype && fstype_is_network(p->fstype))
return false;
if (mount_is_bind(p))
return false;
return fstab_test_option(p->options,
"usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0");
}
2010-04-21 03:27:44 +02:00
static void mount_init(Unit *u) {
Mount *m = MOUNT(u);
2010-04-21 03:27:44 +02:00
assert(u);
assert(u->load_state == UNIT_STUB);
2010-04-21 03:27:44 +02:00
m->timeout_usec = u->manager->default_timeout_start_usec;
m->exec_context.std_output = u->manager->default_std_output;
m->exec_context.std_error = u->manager->default_std_error;
m->directory_mode = 0755;
/* We need to make sure that /usr/bin/mount is always called
* in the same process group as us, so that the autofs kernel
2010-04-21 03:27:44 +02:00
* side doesn't send us another mount request while we are
* already trying to comply its last one. */
m->exec_context.same_pgrp = true;
2010-04-21 03:27:44 +02:00
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
u->ignore_on_isolate = true;
}
static int mount_arm_timer(Mount *m, usec_t usec) {
int r;
assert(m);
if (m->timer_event_source) {
r = sd_event_source_set_time(m->timer_event_source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
}
if (usec == USEC_INFINITY)
return 0;
2015-04-29 16:05:32 +02:00
r = sd_event_add_time(
UNIT(m)->manager->event,
&m->timer_event_source,
CLOCK_MONOTONIC,
usec, 0,
mount_dispatch_timer, m);
2015-04-29 16:05:32 +02:00
if (r < 0)
return r;
(void) sd_event_source_set_description(m->timer_event_source, "mount-timer");
return 0;
}
2010-04-21 03:27:44 +02:00
static void mount_unwatch_control_pid(Mount *m) {
assert(m);
if (m->control_pid <= 0)
return;
unit_unwatch_pid(UNIT(m), m->control_pid);
m->control_pid = 0;
}
static void mount_parameters_done(MountParameters *p) {
assert(p);
free(p->what);
free(p->options);
free(p->fstype);
p->what = p->options = p->fstype = NULL;
}
2010-01-26 21:39:06 +01:00
static void mount_done(Unit *u) {
2010-01-29 06:04:08 +01:00
Mount *m = MOUNT(u);
2010-01-29 06:04:08 +01:00
assert(m);
m->where = mfree(m->where);
2010-01-29 03:18:09 +01:00
mount_parameters_done(&m->parameters_proc_self_mountinfo);
mount_parameters_done(&m->parameters_fragment);
2010-01-29 06:04:08 +01:00
m->exec_runtime = exec_runtime_unref(m->exec_runtime, false);
exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
m->control_command = NULL;
2010-01-29 03:18:09 +01:00
dynamic_creds_unref(&m->dynamic_creds);
2010-04-21 03:27:44 +02:00
mount_unwatch_control_pid(m);
2010-01-29 03:18:09 +01:00
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
2010-01-29 03:18:09 +01:00
}
_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
assert(m);
if (m->from_fragment)
return &m->parameters_fragment;
return NULL;
}
_pure_ static MountParameters* get_mount_parameters(Mount *m) {
assert(m);
if (m->from_proc_self_mountinfo)
return &m->parameters_proc_self_mountinfo;
return get_mount_parameters_fragment(m);
}
static int mount_add_mount_dependencies(Mount *m) {
2010-09-28 01:03:19 +02:00
MountParameters *pm;
Unit *other;
Iterator i;
Set *s;
2010-01-29 02:07:41 +01:00
int r;
assert(m);
2010-01-29 02:07:41 +01:00
if (!path_equal(m->where, "/")) {
_cleanup_free_ char *parent = NULL;
/* Adds in links to other mount points that might lie further up in the hierarchy */
parent = dirname_malloc(m->where);
if (!parent)
return -ENOMEM;
r = unit_require_mounts_for(UNIT(m), parent, UNIT_DEPENDENCY_IMPLICIT);
2013-01-04 21:29:48 +01:00
if (r < 0)
return r;
2013-01-04 21:29:48 +01:00
}
/* Adds in dependencies to other mount points that might be needed for the source path (if this is a bind mount
* or a loop mount) to be available. */
pm = get_mount_parameters_fragment(m);
if (pm && pm->what &&
path_is_absolute(pm->what) &&
(mount_is_bind(pm) || mount_is_loop(pm) || !mount_is_network(pm))) {
r = unit_require_mounts_for(UNIT(m), pm->what, UNIT_DEPENDENCY_FILE);
2013-01-04 21:29:48 +01:00
if (r < 0)
return r;
2013-01-04 21:29:48 +01:00
}
2010-01-29 02:07:41 +01:00
/* Adds in dependencies to other units that use this path or paths further down in the hierarchy */
s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
SET_FOREACH(other, s, i) {
2010-01-29 02:07:41 +01:00
if (other->load_state != UNIT_LOADED)
continue;
2010-01-29 02:07:41 +01:00
if (other == UNIT(m))
continue;
2010-01-29 02:07:41 +01:00
r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true, UNIT_DEPENDENCY_PATH);
2013-01-04 21:29:48 +01:00
if (r < 0)
return r;
2010-01-29 02:07:41 +01:00
if (UNIT(m)->fragment_path) {
/* If we have fragment configuration, then make this dependency required */
r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH);
if (r < 0)
return r;
}
}
return 0;
}
static int mount_add_device_dependencies(Mount *m) {
bool device_wants_mount = false;
UnitDependencyMask mask;
MountParameters *p;
UnitDependency dep;
int r;
assert(m);
p = get_mount_parameters(m);
if (!p)
return 0;
if (!p->what)
return 0;
2010-09-28 01:03:19 +02:00
if (mount_is_bind(p))
return 0;
if (!is_device_path(p->what))
return 0;
/* /dev/root is a really weird thing, it's not a real device,
* but just a path the kernel exports for the root file system
* specified on the kernel command line. Ignore it here. */
if (path_equal(p->what, "/dev/root"))
return 0;
if (path_equal(m->where, "/"))
return 0;
if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager))
device_wants_mount = true;
/* Mount units from /proc/self/mountinfo are not bound to devices
* by default since they're subject to races when devices are
* unplugged. But the user can still force this dep with an
* appropriate option (or udev property) so the mount units are
* automatically stopped when the device disappears suddenly. */
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
if (r < 0)
return r;
return 0;
}
static int mount_add_quota_dependencies(Mount *m) {
UnitDependencyMask mask;
MountParameters *p;
int r;
assert(m);
if (!MANAGER_IS_SYSTEM(UNIT(m)->manager))
return 0;
p = get_mount_parameters_fragment(m);
if (!p)
return 0;
if (!needs_quota(p))
return 0;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, true, mask);
if (r < 0)
return r;
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, true, mask);
if (r < 0)
return r;
return 0;
}
static bool mount_is_extrinsic(Mount *m) {
MountParameters *p;
assert(m);
/* Returns true for all units that are "magic" and should be excluded from the usual start-up and shutdown
* dependencies. We call them "extrinsic" here, as they are generally mounted outside of the systemd dependency
* logic. We shouldn't attempt to manage them ourselves but it's fine if the user operates on them with us. */
if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) /* We only automatically manage mounts if we are in system mode */
return true;
if (PATH_IN_SET(m->where, /* Don't bother with the OS data itself */
"/",
"/usr"))
return true;
if (PATH_STARTSWITH_SET(m->where,
"/run/initramfs", /* This should stay around from before we boot until after we shutdown */
"/proc", /* All of this is API VFS */
"/sys", /* … dito … */
"/dev")) /* … dito … */
return true;
/* If this is an initrd mount, and we are not in the initrd, then leave this around forever, too. */
p = get_mount_parameters(m);
if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd())
return true;
return false;
}
static int mount_add_default_dependencies(Mount *m) {
UnitDependencyMask mask;
int r;
MountParameters *p;
const char *after;
assert(m);
if (!UNIT(m)->default_dependencies)
return 0;
/* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are guaranteed to stay
* mounted the whole time, since our system is on it. Also, don't bother with anything mounted below virtual
* file systems, it's also going to be virtual, and hence not worth the effort. */
if (mount_is_extrinsic(m))
return 0;
p = get_mount_parameters(m);
if (!p)
return 0;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
if (mount_is_network(p)) {
/* We order ourselves after network.target. This is
* primarily useful at shutdown: services that take
* down the network should order themselves before
* network.target, so that they are shut down only
* after this mount unit is stopped. */
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, true, mask);
if (r < 0)
return r;
/* We pull in network-online.target, and order
* ourselves after it. This is useful at start-up to
* actively pull in tools that want to be started
* before we start mounting network file systems, and
* whose purpose it is to delay this until the network
* is "up". */
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, true, mask);
if (r < 0)
return r;
after = SPECIAL_REMOTE_FS_PRE_TARGET;
} else
after = SPECIAL_LOCAL_FS_PRE_TARGET;
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
if (r < 0)
return r;
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, mask);
if (r < 0)
return r;
/* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */
2017-11-12 14:25:58 +01:00
if (streq_ptr(p->fstype, "tmpfs")) {
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, true, mask);
if (r < 0)
return r;
}
return 0;
}
static int mount_verify(Mount *m) {
_cleanup_free_ char *e = NULL;
MountParameters *p;
int r;
assert(m);
if (UNIT(m)->load_state != UNIT_LOADED)
return 0;
if (!m->from_fragment && !m->from_proc_self_mountinfo && !UNIT(m)->perpetual)
return -ENOENT;
r = unit_name_from_path(m->where, ".mount", &e);
if (r < 0)
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
return log_unit_error_errno(UNIT(m), r, "Failed to generate unit name from mount path: %m");
if (!unit_has_name(UNIT(m), e)) {
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_error(UNIT(m), "Where= setting doesn't match unit name. Refusing.");
return -ENOEXEC;
}
if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_error(UNIT(m), "Cannot create mount unit for API file system %s. Refusing.", m->where);
return -ENOEXEC;
}
p = get_mount_parameters_fragment(m);
if (p && !p->what) {
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_error(UNIT(m), "What= setting is missing. Refusing.");
return -ENOEXEC;
2010-05-14 02:29:45 +02:00
}
if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_error(UNIT(m), "Unit has PAM enabled. Kill mode must be set to control-group'. Refusing.");
return -ENOEXEC;
}
return 0;
}
static int mount_add_extras(Mount *m) {
Unit *u = UNIT(m);
int r;
assert(m);
if (u->fragment_path)
m->from_fragment = true;
if (!m->where) {
r = unit_name_to_path(u->id, &m->where);
if (r < 0)
return r;
}
2010-04-21 03:27:44 +02:00
path_simplify(m->where, false);
if (!u->description) {
r = unit_set_description(u, m->where);
if (r < 0)
return r;
}
r = mount_add_device_dependencies(m);
if (r < 0)
return r;
r = mount_add_mount_dependencies(m);
if (r < 0)
return r;
r = mount_add_quota_dependencies(m);
if (r < 0)
return r;
r = unit_patch_contexts(u);
if (r < 0)
return r;
r = unit_add_exec_dependencies(u, &m->exec_context);
if (r < 0)
return r;
r = unit_set_default_slice(u);
if (r < 0)
return r;
r = mount_add_default_dependencies(m);
if (r < 0)
return r;
return 0;
}
static int mount_load_root_mount(Unit *u) {
assert(u);
if (!unit_has_name(u, SPECIAL_ROOT_MOUNT))
return 0;
u->perpetual = true;
u->default_dependencies = false;
/* The stdio/kmsg bridge socket is on /, in order to avoid a dep loop, don't use kmsg logging for -.mount */
MOUNT(u)->exec_context.std_output = EXEC_OUTPUT_NULL;
MOUNT(u)->exec_context.std_input = EXEC_INPUT_NULL;
if (!u->description)
u->description = strdup("Root Mount");
return 1;
}
static int mount_load(Unit *u) {
Mount *m = MOUNT(u);
int r;
assert(u);
assert(u->load_state == UNIT_STUB);
r = mount_load_root_mount(u);
if (r < 0)
return r;
if (m->from_proc_self_mountinfo || u->perpetual)
r = unit_load_fragment_and_dropin_optional(u);
else
r = unit_load_fragment_and_dropin(u);
if (r < 0)
return r;
/* This is a new unit? Then let's add in some extras */
if (u->load_state == UNIT_LOADED) {
r = mount_add_extras(m);
if (r < 0)
return r;
}
return mount_verify(m);
}
static void mount_set_state(Mount *m, MountState state) {
MountState old_state;
assert(m);
old_state = m->state;
m->state = state;
if (!MOUNT_STATE_WITH_PROCESS(state)) {
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
2010-04-21 03:27:44 +02:00
mount_unwatch_control_pid(m);
m->control_command = NULL;
2010-04-21 03:27:44 +02:00
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
}
if (state != old_state)
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state));
unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state],
m->reload_result == MOUNT_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE);
}
static int mount_coldplug(Unit *u) {
Mount *m = MOUNT(u);
2010-04-21 03:27:44 +02:00
MountState new_state = MOUNT_DEAD;
int r;
assert(m);
assert(m->state == MOUNT_DEAD);
2010-04-21 03:27:44 +02:00
if (m->deserialized_state != m->state)
new_state = m->deserialized_state;
else if (m->from_proc_self_mountinfo)
new_state = MOUNT_MOUNTED;
if (new_state == m->state)
return 0;
if (m->control_pid > 0 &&
pid_is_unwaited(m->control_pid) &&
MOUNT_STATE_WITH_PROCESS(new_state)) {
r = unit_watch_pid(UNIT(m), m->control_pid);
if (r < 0)
return r;
r = mount_arm_timer(m, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec));
if (r < 0)
return r;
2010-04-21 03:27:44 +02:00
}
if (!IN_SET(new_state, MOUNT_DEAD, MOUNT_FAILED)) {
(void) unit_setup_dynamic_creds(u);
(void) unit_setup_exec_runtime(u);
}
mount_set_state(m, new_state);
return 0;
}
static void mount_dump(Unit *u, FILE *f, const char *prefix) {
char buf[FORMAT_TIMESPAN_MAX];
Mount *m = MOUNT(u);
MountParameters *p;
assert(m);
assert(f);
p = get_mount_parameters(m);
fprintf(f,
"%sMount State: %s\n"
"%sResult: %s\n"
"%sWhere: %s\n"
"%sWhat: %s\n"
"%sFile System Type: %s\n"
"%sOptions: %s\n"
"%sFrom /proc/self/mountinfo: %s\n"
"%sFrom fragment: %s\n"
"%sExtrinsic: %s\n"
"%sDirectoryMode: %04o\n"
"%sSloppyOptions: %s\n"
"%sLazyUnmount: %s\n"
2018-01-30 09:09:59 +01:00
"%sForceUnmount: %s\n"
"%sTimoutSec: %s\n",
2010-04-21 03:27:44 +02:00
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
prefix, m->where,
prefix, p ? strna(p->what) : "n/a",
prefix, p ? strna(p->fstype) : "n/a",
prefix, p ? strna(p->options) : "n/a",
prefix, yes_no(m->from_proc_self_mountinfo),
prefix, yes_no(m->from_fragment),
prefix, yes_no(mount_is_extrinsic(m)),
prefix, m->directory_mode,
prefix, yes_no(m->sloppy_options),
prefix, yes_no(m->lazy_unmount),
2018-01-30 09:09:59 +01:00
prefix, yes_no(m->force_unmount),
prefix, format_timespan(buf, sizeof(buf), m->timeout_usec, USEC_PER_SEC));
if (m->control_pid > 0)
fprintf(f,
"%sControl PID: "PID_FMT"\n",
prefix, m->control_pid);
exec_context_dump(&m->exec_context, f, prefix);
kill_context_dump(&m->kill_context, f, prefix);
cgroup_context_dump(&m->cgroup_context, f, prefix);
}
2010-04-21 03:27:44 +02:00
static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
_cleanup_(exec_params_clear) ExecParameters exec_params = {
.flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
.stdin_fd = -1,
.stdout_fd = -1,
.stderr_fd = -1,
.exec_fd = -1,
};
pid_t pid;
int r;
2010-04-21 03:27:44 +02:00
assert(m);
assert(c);
assert(_pid);
r = unit_prepare_exec(UNIT(m));
if (r < 0)
return r;
r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
2012-11-23 21:37:58 +01:00
if (r < 0)
return r;
2010-04-21 03:27:44 +02:00
r = unit_set_exec_params(UNIT(m), &exec_params);
if (r < 0)
return r;
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
r = exec_spawn(UNIT(m),
c,
&m->exec_context,
&exec_params,
m->exec_runtime,
&m->dynamic_creds,
&pid);
if (r < 0)
return r;
2010-04-21 03:27:44 +02:00
r = unit_watch_pid(UNIT(m), pid);
if (r < 0)
2010-04-21 03:27:44 +02:00
/* FIXME: we need to do something here */
return r;
2010-04-21 03:27:44 +02:00
*_pid = pid;
return 0;
}
2012-02-03 03:10:56 +01:00
static void mount_enter_dead(Mount *m, MountResult f) {
assert(m);
if (m->result == MOUNT_SUCCESS)
2012-02-03 03:10:56 +01:00
m->result = f;
unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result));
mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
m->exec_runtime = exec_runtime_unref(m->exec_runtime, true);
exec_context_destroy_runtime_directory(&m->exec_context, UNIT(m)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
unit_unref_uid_gid(UNIT(m), true);
dynamic_creds_destroy(&m->dynamic_creds);
}
2012-02-03 03:10:56 +01:00
static void mount_enter_mounted(Mount *m, MountResult f) {
assert(m);
if (m->result == MOUNT_SUCCESS)
2012-02-03 03:10:56 +01:00
m->result = f;
mount_set_state(m, MOUNT_MOUNTED);
}
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
static void mount_enter_dead_or_mounted(Mount *m, MountResult f) {
assert(m);
/* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point. We use this
* whenever we executed an operation, so that our internal state reflects what the kernel says again, after all
* ultimately we just mirror the kernel's internal state on this. */
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, f);
else
mount_enter_dead(m, f);
}
static int state_to_kill_operation(MountState state) {
switch (state) {
case MOUNT_REMOUNTING_SIGTERM:
case MOUNT_UNMOUNTING_SIGTERM:
return KILL_TERMINATE;
case MOUNT_REMOUNTING_SIGKILL:
case MOUNT_UNMOUNTING_SIGKILL:
return KILL_KILL;
default:
return _KILL_OPERATION_INVALID;
}
}
2012-02-03 03:10:56 +01:00
static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
int r;
assert(m);
if (m->result == MOUNT_SUCCESS)
2012-02-03 03:10:56 +01:00
m->result = f;
r = unit_kill_context(
UNIT(m),
&m->kill_context,
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
state_to_kill_operation(state),
-1,
m->control_pid,
false);
if (r < 0)
goto fail;
if (r > 0) {
r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
2012-11-23 21:37:58 +01:00
if (r < 0)
goto fail;
mount_set_state(m, state);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
} else if (state == MOUNT_REMOUNTING_SIGTERM && m->kill_context.send_sigkill)
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
else if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL))
2012-02-03 03:10:56 +01:00
mount_enter_mounted(m, MOUNT_SUCCESS);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
else if (state == MOUNT_UNMOUNTING_SIGTERM && m->kill_context.send_sigkill)
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
else
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
return;
fail:
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m");
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
2014-08-15 01:05:47 +02:00
}
2012-02-03 03:10:56 +01:00
static void mount_enter_unmounting(Mount *m) {
int r;
assert(m);
/* Start counting our attempts */
if (!IN_SET(m->state,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
MOUNT_UNMOUNTING_SIGKILL))
m->n_retry_umount = 0;
2010-04-21 03:27:44 +02:00
m->control_command_id = MOUNT_EXEC_UNMOUNT;
m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, "-c", NULL);
if (r >= 0 && m->lazy_unmount)
r = exec_command_append(m->control_command, "-l", NULL);
if (r >= 0 && m->force_unmount)
r = exec_command_append(m->control_command, "-f", NULL);
if (r < 0)
goto fail;
2010-04-21 03:27:44 +02:00
mount_unwatch_control_pid(m);
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
goto fail;
mount_set_state(m, MOUNT_UNMOUNTING);
return;
fail:
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_warning_errno(UNIT(m), r, "Failed to run 'umount' task: %m");
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
}
static void mount_enter_mounting(Mount *m) {
int r;
MountParameters *p;
assert(m);
r = unit_fail_if_noncanonical(UNIT(m), m->where);
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
if (r < 0)
goto fail;
(void) mkdir_p_label(m->where, m->directory_mode);
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
unit_warn_if_dir_nonempty(UNIT(m), m->where);
unit_warn_leftover_processes(UNIT(m));
m->control_command_id = MOUNT_EXEC_MOUNT;
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
/* Create the source directory for bind-mounts if needed */
p = get_mount_parameters_fragment(m);
if (p && mount_is_bind(p))
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
(void) mkdir_p_label(p->what, m->directory_mode);
2014-08-15 01:05:47 +02:00
if (p) {
_cleanup_free_ char *opts = NULL;
r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, &opts);
if (r < 0)
goto fail;
r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL);
if (r >= 0 && m->sloppy_options)
r = exec_command_append(m->control_command, "-s", NULL);
if (r >= 0 && p->fstype)
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
if (r >= 0 && !isempty(opts))
r = exec_command_append(m->control_command, "-o", opts, NULL);
} else
r = -ENOENT;
if (r < 0)
goto fail;
2010-04-21 03:27:44 +02:00
mount_unwatch_control_pid(m);
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
goto fail;
mount_set_state(m, MOUNT_MOUNTING);
return;
fail:
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_warning_errno(UNIT(m), r, "Failed to run 'mount' task: %m");
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
}
static void mount_set_reload_result(Mount *m, MountResult result) {
assert(m);
/* Only store the first error we encounter */
if (m->reload_result != MOUNT_SUCCESS)
return;
m->reload_result = result;
}
2012-02-03 03:10:56 +01:00
static void mount_enter_remounting(Mount *m) {
int r;
MountParameters *p;
assert(m);
/* Reset reload result when we are about to start a new remount operation */
m->reload_result = MOUNT_SUCCESS;
2010-04-21 03:27:44 +02:00
m->control_command_id = MOUNT_EXEC_REMOUNT;
m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
p = get_mount_parameters_fragment(m);
if (p) {
const char *o;
if (p->options)
o = strjoina("remount,", p->options);
else
o = "remount";
r = exec_command_set(m->control_command, MOUNT_PATH,
p->what, m->where,
"-o", o, NULL);
if (r >= 0 && m->sloppy_options)
r = exec_command_append(m->control_command, "-s", NULL);
if (r >= 0 && p->fstype)
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
} else
r = -ENOENT;
2010-10-12 04:06:21 +02:00
if (r < 0)
goto fail;
2010-04-21 03:27:44 +02:00
mount_unwatch_control_pid(m);
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
goto fail;
mount_set_state(m, MOUNT_REMOUNTING);
return;
fail:
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_warning_errno(UNIT(m), r, "Failed to run 'remount' task: %m");
mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
}
static int mount_start(Unit *u) {
Mount *m = MOUNT(u);
int r;
assert(m);
/* We cannot fulfill this request right now, try again later
* please! */
if (IN_SET(m->state,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
MOUNT_UNMOUNTING_SIGKILL))
return -EAGAIN;
/* Already on it! */
2010-10-12 04:06:21 +02:00
if (m->state == MOUNT_MOUNTING)
return 0;
assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED));
r = unit_start_limit_test(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
return r;
}
core: add "invocation ID" concept to service manager This adds a new invocation ID concept to the service manager. The invocation ID identifies each runtime cycle of a unit uniquely. A new randomized 128bit ID is generated each time a unit moves from and inactive to an activating or active state. The primary usecase for this concept is to connect the runtime data PID 1 maintains about a service with the offline data the journal stores about it. Previously we'd use the unit name plus start/stop times, which however is highly racy since the journal will generally process log data after the service already ended. The "invocation ID" kinda matches the "boot ID" concept of the Linux kernel, except that it applies to an individual unit instead of the whole system. The invocation ID is passed to the activated processes as environment variable. It is additionally stored as extended attribute on the cgroup of the unit. The latter is used by journald to automatically retrieve it for each log logged message and attach it to the log entry. The environment variable is very easily accessible, even for unprivileged services. OTOH the extended attribute is only accessible to privileged processes (this is because cgroupfs only supports the "trusted." xattr namespace, not "user."). The environment variable may be altered by services, the extended attribute may not be, hence is the better choice for the journal. Note that reading the invocation ID off the extended attribute from journald is racy, similar to the way reading the unit name for a logging process is. This patch adds APIs to read the invocation ID to sd-id128: sd_id128_get_invocation() may be used in a similar fashion to sd_id128_get_boot(). PID1's own logging is updated to always include the invocation ID when it logs information about a unit. A new bus call GetUnitByInvocationID() is added that allows retrieving a bus path to a unit by its invocation ID. The bus path is built using the invocation ID, thus providing a path for referring to a unit that is valid only for the current runtime cycleof it. Outlook for the future: should the kernel eventually allow passing of cgroup information along AF_UNIX/SOCK_DGRAM messages via a unique cgroup id, then we can alter the invocation ID to be generated as hash from that rather than entirely randomly. This way we can derive the invocation race-freely from the messages.
2016-08-30 23:18:46 +02:00
r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
2012-02-03 03:10:56 +01:00
m->result = MOUNT_SUCCESS;
m->reload_result = MOUNT_SUCCESS;
exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
u->reset_accounting = true;
2012-02-03 03:10:56 +01:00
mount_enter_mounting(m);
return 1;
}
static int mount_stop(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
switch (m->state) {
case MOUNT_UNMOUNTING:
case MOUNT_UNMOUNTING_SIGKILL:
case MOUNT_UNMOUNTING_SIGTERM:
/* Already on it */
return 0;
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
case MOUNT_MOUNTING:
case MOUNT_MOUNTING_DONE:
case MOUNT_REMOUNTING:
/* If we are still waiting for /bin/mount, we go directly into kill mode. */
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_SUCCESS);
return 0;
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
case MOUNT_REMOUNTING_SIGTERM:
/* If we are already waiting for a hung remount, convert this to the matching unmounting state */
mount_set_state(m, MOUNT_UNMOUNTING_SIGTERM);
return 0;
case MOUNT_REMOUNTING_SIGKILL:
/* as above */
mount_set_state(m, MOUNT_UNMOUNTING_SIGKILL);
return 0;
case MOUNT_MOUNTED:
mount_enter_unmounting(m);
return 1;
default:
assert_not_reached("Unexpected state.");
}
}
static int mount_reload(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
assert(m->state == MOUNT_MOUNTED);
2012-02-03 03:10:56 +01:00
mount_enter_remounting(m);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
return 1;
}
2010-04-21 03:27:44 +02:00
static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
Mount *m = MOUNT(u);
assert(m);
assert(f);
assert(fds);
(void) serialize_item(f, "state", mount_state_to_string(m->state));
(void) serialize_item(f, "result", mount_result_to_string(m->result));
(void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result));
2010-04-21 03:27:44 +02:00
if (m->control_pid > 0)
(void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid);
2010-04-21 03:27:44 +02:00
if (m->control_command_id >= 0)
(void) serialize_item(f, "control-command", mount_exec_command_to_string(m->control_command_id));
2010-04-21 03:27:44 +02:00
return 0;
}
static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Mount *m = MOUNT(u);
assert(u);
assert(key);
assert(value);
assert(fds);
if (streq(key, "state")) {
MountState state;
if ((state = mount_state_from_string(value)) < 0)
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_debug(u, "Failed to parse state value: %s", value);
2010-04-21 03:27:44 +02:00
else
m->deserialized_state = state;
2012-02-03 03:10:56 +01:00
} else if (streq(key, "result")) {
MountResult f;
2010-04-21 03:27:44 +02:00
2012-02-03 03:10:56 +01:00
f = mount_result_from_string(value);
if (f < 0)
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_debug(u, "Failed to parse result value: %s", value);
2012-02-03 03:10:56 +01:00
else if (f != MOUNT_SUCCESS)
m->result = f;
} else if (streq(key, "reload-result")) {
MountResult f;
f = mount_result_from_string(value);
if (f < 0)
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_debug(u, "Failed to parse reload result value: %s", value);
2012-02-03 03:10:56 +01:00
else if (f != MOUNT_SUCCESS)
m->reload_result = f;
2010-04-21 03:27:44 +02:00
} else if (streq(key, "control-pid")) {
pid_t pid;
2010-04-21 03:27:44 +02:00
if (parse_pid(value, &pid) < 0)
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_debug(u, "Failed to parse control-pid value: %s", value);
2010-04-21 03:27:44 +02:00
else
m->control_pid = pid;
2010-04-21 03:27:44 +02:00
} else if (streq(key, "control-command")) {
MountExecCommand id;
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
id = mount_exec_command_from_string(value);
if (id < 0)
log_unit_debug(u, "Failed to parse exec-command value: %s", value);
2010-04-21 03:27:44 +02:00
else {
m->control_command_id = id;
m->control_command = m->exec_command + id;
}
} else
core,network: major per-object logging rework This changes log_unit_info() (and friends) to take a real Unit* object insted of just a unit name as parameter. The call will now prefix all logged messages with the unit name, thus allowing the unit name to be dropped from the various passed romat strings, simplifying invocations drastically, and unifying log output across messages. Also, UNIT= vs. USER_UNIT= is now derived from the Manager object attached to the Unit object, instead of getpid(). This has the benefit of correcting the field for --test runs. Also contains a couple of other logging improvements: - Drops a couple of strerror() invocations in favour of using %m. - Not only .mount units now warn if a symlinks exist for the mount point already, .automount units do that too, now. - A few invocations of log_struct() that didn't actually pass any additional structured data have been replaced by simpler invocations of log_unit_info() and friends. - For structured data a new LOG_UNIT_MESSAGE() macro has been added, that works like LOG_MESSAGE() but prefixes the message with the unit name. Similar, there's now LOG_LINK_MESSAGE() and LOG_NETDEV_MESSAGE(). - For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(), LOG_NETDEV_INTERFACE() macros have been added that generate the necessary per object fields. The old log_unit_struct() call has been removed in favour of these new macros used in raw log_struct() invocations. In addition to removing one more function call this allows generated structured log messages that contain two object fields, as necessary for example for network interfaces that are joined into another network interface, and whose messages shall be indexed by both. - The LOG_ERRNO() macro has been removed, in favour of log_struct_errno(). The latter has the benefit of ensuring that %m in format strings is properly resolved to the specified error number. - A number of logging messages have been converted to use log_unit_info() instead of log_info() - The client code in sysv-generator no longer #includes core code from src/core/. - log_unit_full_errno() has been removed, log_unit_full() instead takes an errno now, too. - log_unit_info(), log_link_info(), log_netdev_info() and friends, now avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
log_unit_debug(u, "Unknown serialization key: %s", key);
2010-04-21 03:27:44 +02:00
return 0;
}
_pure_ static UnitActiveState mount_active_state(Unit *u) {
assert(u);
return state_translation_table[MOUNT(u)->state];
}
_pure_ static const char *mount_sub_state_to_string(Unit *u) {
assert(u);
2010-04-21 03:27:44 +02:00
return mount_state_to_string(MOUNT(u)->state);
}
_pure_ static bool mount_may_gc(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
if (m->from_proc_self_mountinfo)
return false;
return true;
}
static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Mount *m = MOUNT(u);
2012-02-03 03:10:56 +01:00
MountResult f;
assert(m);
assert(pid >= 0);
if (pid != m->control_pid)
return;
m->control_pid = 0;
if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
2012-02-03 03:10:56 +01:00
f = MOUNT_SUCCESS;
else if (code == CLD_EXITED)
f = MOUNT_FAILURE_EXIT_CODE;
else if (code == CLD_KILLED)
f = MOUNT_FAILURE_SIGNAL;
else if (code == CLD_DUMPED)
f = MOUNT_FAILURE_CORE_DUMP;
else
assert_not_reached("Unknown code");
if (IN_SET(m->state, MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM))
mount_set_reload_result(m, f);
else if (m->result == MOUNT_SUCCESS)
2012-02-03 03:10:56 +01:00
m->result = f;
2010-04-21 03:27:44 +02:00
if (m->control_command) {
exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
2012-02-03 03:10:56 +01:00
2010-04-21 03:27:44 +02:00
m->control_command = NULL;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
}
unit_log_process_exit(
u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
"Mount process",
mount_exec_command_to_string(m->control_command_id),
code, status);
/* Note that due to the io event priority logic, we can be sure the new mountinfo is loaded
* before we process the SIGCHLD for the mount command. */
switch (m->state) {
case MOUNT_MOUNTING:
/* Our mount point has not appeared in mountinfo. Something went wrong. */
if (f == MOUNT_SUCCESS) {
/* Either /bin/mount has an unexpected definition of success,
* or someone raced us and we lost. */
log_unit_warning(UNIT(m), "Mount process finished, but there is no mount.");
f = MOUNT_FAILURE_PROTOCOL;
}
mount_enter_dead(m, f);
break;
case MOUNT_MOUNTING_DONE:
mount_enter_mounted(m, f);
break;
case MOUNT_REMOUNTING:
case MOUNT_REMOUNTING_SIGTERM:
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
case MOUNT_REMOUNTING_SIGKILL:
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
break;
case MOUNT_UNMOUNTING:
if (f == MOUNT_SUCCESS && m->from_proc_self_mountinfo) {
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
/* Still a mount point? If so, let's try again. Most likely there were multiple mount points
* stacked on top of each other. We might exceed the timeout specified by the user overall,
* but we will stop as soon as any one umount times out. */
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
log_unit_debug(u, "Mount still present, trying again.");
m->n_retry_umount++;
mount_enter_unmounting(m);
} else {
log_unit_warning(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_mounted(m, f);
}
} else
mount_enter_dead_or_mounted(m, f);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
break;
case MOUNT_UNMOUNTING_SIGKILL:
case MOUNT_UNMOUNTING_SIGTERM:
mount_enter_dead_or_mounted(m, f);
break;
default:
assert_not_reached("Uh, control process died at wrong time.");
}
/* Notify clients about changed exit status */
unit_add_to_dbus_queue(u);
}
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
Mount *m = MOUNT(userdata);
assert(m);
assert(m->timer_event_source == source);
switch (m->state) {
case MOUNT_MOUNTING:
case MOUNT_MOUNTING_DONE:
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Mounting timed out. Terminating.");
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
break;
case MOUNT_REMOUNTING:
log_unit_warning(UNIT(m), "Remounting timed out. Terminating remount process.");
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
mount_enter_signal(m, MOUNT_REMOUNTING_SIGTERM, MOUNT_SUCCESS);
break;
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
case MOUNT_REMOUNTING_SIGTERM:
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
if (m->kill_context.send_sigkill) {
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Remounting timed out. Killing.");
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
} else {
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
}
break;
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
case MOUNT_REMOUNTING_SIGKILL:
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
break;
case MOUNT_UNMOUNTING:
log_unit_warning(UNIT(m), "Unmounting timed out. Terminating.");
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
break;
case MOUNT_UNMOUNTING_SIGTERM:
if (m->kill_context.send_sigkill) {
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Mount process timed out. Killing.");
2012-02-03 03:10:56 +01:00
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
} else {
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Mount process timed out. Skipping SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
}
break;
case MOUNT_UNMOUNTING_SIGKILL:
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
return 0;
}
typedef struct {
bool is_mounted;
bool just_mounted;
bool just_changed;
} MountSetupFlags;
static int mount_setup_new_unit(
Unit *u,
const char *what,
const char *where,
const char *options,
const char *fstype,
MountSetupFlags *flags) {
MountParameters *p;
assert(u);
assert(flags);
u->source_path = strdup("/proc/self/mountinfo");
MOUNT(u)->where = strdup(where);
if (!u->source_path || !MOUNT(u)->where)
return -ENOMEM;
/* Make sure to initialize those fields before mount_is_extrinsic(). */
MOUNT(u)->from_proc_self_mountinfo = true;
p = &MOUNT(u)->parameters_proc_self_mountinfo;
p->what = strdup(what);
p->options = strdup(options);
p->fstype = strdup(fstype);
if (!p->what || !p->options || !p->fstype)
return -ENOMEM;
if (!mount_is_extrinsic(MOUNT(u))) {
const char *target;
int r;
target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
if (r < 0)
return r;
r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
if (r < 0)
return r;
}
unit_add_to_load_queue(u);
flags->is_mounted = true;
flags->just_mounted = true;
flags->just_changed = true;
return 0;
}
static int mount_setup_existing_unit(
Unit *u,
const char *what,
const char *where,
const char *options,
const char *fstype,
MountSetupFlags *flags) {
MountParameters *p;
bool load_extras = false;
int r1, r2, r3;
assert(u);
assert(flags);
if (!MOUNT(u)->where) {
MOUNT(u)->where = strdup(where);
if (!MOUNT(u)->where)
return -ENOMEM;
}
/* Make sure to initialize those fields before mount_is_extrinsic(). */
p = &MOUNT(u)->parameters_proc_self_mountinfo;
r1 = free_and_strdup(&p->what, what);
r2 = free_and_strdup(&p->options, options);
r3 = free_and_strdup(&p->fstype, fstype);
if (r1 < 0 || r2 < 0 || r3 < 0)
return -ENOMEM;
flags->just_changed = r1 > 0 || r2 > 0 || r3 > 0;
flags->is_mounted = true;
flags->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted;
MOUNT(u)->from_proc_self_mountinfo = true;
if (!mount_is_extrinsic(MOUNT(u)) && mount_is_network(p)) {
/* _netdev option may have shown up late, or on a
* remount. Add remote-fs dependencies, even though
* local-fs ones may already be there.
*
* Note: due to a current limitation (we don't track
* in the dependency "Set*" objects who created a
* dependency), we can only add deps, never lose them,
* until the next full daemon-reload. */
unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
load_extras = true;
}
if (u->load_state == UNIT_NOT_FOUND) {
u->load_state = UNIT_LOADED;
u->load_error = 0;
/* Load in the extras later on, after we
* finished initialization of the unit */
/* FIXME: since we're going to load the unit later on, why setting load_extras=true ? */
load_extras = true;
flags->just_changed = true;
}
if (load_extras)
return mount_add_extras(MOUNT(u));
return 0;
}
static int mount_setup_unit(
Manager *m,
const char *what,
const char *where,
const char *options,
const char *fstype,
bool set_flags) {
_cleanup_free_ char *e = NULL;
MountSetupFlags flags;
Unit *u;
int r;
2010-01-29 02:07:41 +01:00
2010-01-29 03:18:09 +01:00
assert(m);
2010-01-29 02:07:41 +01:00
assert(what);
assert(where);
assert(options);
assert(fstype);
/* Ignore API mount points. They should never be referenced in
* dependencies ever. */
if (mount_point_is_api(where) || mount_point_ignore(where))
return 0;
2010-01-29 02:07:41 +01:00
if (streq(fstype, "autofs"))
return 0;
2010-05-14 02:29:45 +02:00
/* probably some kind of swap, ignore */
if (!is_path(where))
2010-01-29 02:07:41 +01:00
return 0;
r = unit_name_from_path(where, ".mount", &e);
if (r < 0)
return r;
2010-01-29 02:07:41 +01:00
u = manager_get_unit(m, e);
if (!u) {
/* First time we see this mount point meaning that it's
* not been initiated by a mount unit but rather by the
* sysadmin having called mount(8) directly. */
r = unit_new_for_name(m, sizeof(Mount), e, &u);
2010-01-29 02:07:41 +01:00
if (r < 0)
goto fail;
r = mount_setup_new_unit(u, what, where, options, fstype, &flags);
if (r < 0)
unit_free(u);
} else
r = mount_setup_existing_unit(u, what, where, options, fstype, &flags);
2010-01-29 02:07:41 +01:00
if (r < 0)
goto fail;
if (set_flags) {
MOUNT(u)->is_mounted = flags.is_mounted;
MOUNT(u)->just_mounted = flags.just_mounted;
MOUNT(u)->just_changed = flags.just_changed;
}
if (flags.just_changed)
unit_add_to_dbus_queue(u);
2010-01-29 02:07:41 +01:00
return 0;
fail:
return log_warning_errno(r, "Failed to set up mount unit: %m");
2010-01-29 02:07:41 +01:00
}
2010-01-29 06:04:08 +01:00
static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
_cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
_cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
2010-10-12 04:06:21 +02:00
int r = 0;
2010-01-29 02:07:41 +01:00
assert(m);
t = mnt_new_table();
i = mnt_new_iter(MNT_ITER_FORWARD);
if (!t || !i)
return log_oom();
r = mnt_table_parse_mtab(t, NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
r = 0;
for (;;) {
struct libmnt_fs *fs;
const char *device, *path, *options, *fstype;
_cleanup_free_ char *d = NULL, *p = NULL;
int k;
2010-01-29 02:07:41 +01:00
k = mnt_table_next_fs(t, i, &fs);
if (k == 1)
break;
if (k < 0)
return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m");
device = mnt_fs_get_source(fs);
path = mnt_fs_get_target(fs);
options = mnt_fs_get_options(fs);
fstype = mnt_fs_get_fstype(fs);
if (!device || !path)
continue;
if (cunescape(device, UNESCAPE_RELAX, &d) < 0)
return log_oom();
if (cunescape(path, UNESCAPE_RELAX, &p) < 0)
return log_oom();
2010-01-29 02:07:41 +01:00
device_found_node(m, d, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT);
k = mount_setup_unit(m, d, p, options, fstype, set_flags);
if (r == 0 && k < 0)
2010-10-12 04:06:21 +02:00
r = k;
2010-01-29 02:07:41 +01:00
}
return r;
}
static void mount_shutdown(Manager *m) {
assert(m);
m->mount_event_source = sd_event_source_unref(m->mount_event_source);
mnt_unref_monitor(m->mount_monitor);
m->mount_monitor = NULL;
2010-01-29 02:07:41 +01:00
}
static int mount_get_timeout(Unit *u, usec_t *timeout) {
Mount *m = MOUNT(u);
usec_t t;
int r;
if (!m->timer_event_source)
return 0;
r = sd_event_source_get_time(m->timer_event_source, &t);
if (r < 0)
return r;
if (t == USEC_INFINITY)
return 0;
*timeout = t;
return 1;
}
static void mount_enumerate_perpetual(Manager *m) {
Unit *u;
int r;
assert(m);
/* Whatever happens, we know for sure that the root directory is around, and cannot go away. Let's
* unconditionally synthesize it here and mark it as perpetual. */
u = manager_get_unit(m, SPECIAL_ROOT_MOUNT);
if (!u) {
r = unit_new_for_name(m, sizeof(Mount), SPECIAL_ROOT_MOUNT, &u);
if (r < 0) {
log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m");
return;
}
}
u->perpetual = true;
MOUNT(u)->deserialized_state = MOUNT_MOUNTED;
unit_add_to_load_queue(u);
unit_add_to_dbus_queue(u);
}
static bool mount_is_mounted(Mount *m) {
assert(m);
return UNIT(m)->perpetual || m->is_mounted;
}
static void mount_enumerate(Manager *m) {
2010-01-29 02:07:41 +01:00
int r;
2010-01-29 02:07:41 +01:00
assert(m);
mnt_init_debug(0);
if (!m->mount_monitor) {
int fd;
2010-01-29 06:04:08 +01:00
m->mount_monitor = mnt_new_monitor();
if (!m->mount_monitor) {
log_oom();
goto fail;
}
r = mnt_monitor_enable_kernel(m->mount_monitor, 1);
if (r < 0) {
log_error_errno(r, "Failed to enable watching of kernel mount events: %m");
goto fail;
}
r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL);
if (r < 0) {
log_error_errno(r, "Failed to enable watching of userspace mount events: %m");
goto fail;
}
/* mnt_unref_monitor() will close the fd */
fd = r = mnt_monitor_get_fd(m->mount_monitor);
if (r < 0) {
log_error_errno(r, "Failed to acquire watch file descriptor: %m");
goto fail;
}
r = sd_event_add_io(m->event, &m->mount_event_source, fd, EPOLLIN, mount_dispatch_io, m);
if (r < 0) {
log_error_errno(r, "Failed to watch mount file descriptor: %m");
goto fail;
}
r = sd_event_source_set_priority(m->mount_event_source, SD_EVENT_PRIORITY_NORMAL-10);
if (r < 0) {
log_error_errno(r, "Failed to adjust mount watch priority: %m");
goto fail;
}
2015-04-29 16:05:32 +02:00
(void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch");
}
r = mount_load_proc_self_mountinfo(m, false);
if (r < 0)
2010-01-29 02:07:41 +01:00
goto fail;
return;
2010-01-29 02:07:41 +01:00
fail:
mount_shutdown(m);
}
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
_cleanup_set_free_ Set *around = NULL, *gone = NULL;
Manager *m = userdata;
const char *what;
Iterator i;
Unit *u;
2010-01-29 06:04:08 +01:00
int r;
assert(m);
assert(revents & EPOLLIN);
2010-01-29 06:04:08 +01:00
if (fd == mnt_monitor_get_fd(m->mount_monitor)) {
2014-12-10 00:52:56 +01:00
bool rescan = false;
/* Drain all events and verify that the event is valid.
*
* Note that libmount also monitors /run/mount mkdir if the
* directory does not exist yet. The mkdir may generate event
* which is irrelevant for us.
*
* error: r < 0; valid: r == 0, false positive: rc == 1 */
do {
r = mnt_monitor_next_change(m->mount_monitor, NULL, NULL);
if (r == 0)
rescan = true;
else if (r < 0)
return log_error_errno(r, "Failed to drain libmount events: %m");
} while (r == 0);
log_debug("libmount event [rescan: %s]", yes_no(rescan));
if (!rescan)
return 0;
}
2010-01-29 06:04:08 +01:00
2013-01-04 21:29:48 +01:00
r = mount_load_proc_self_mountinfo(m, true);
if (r < 0) {
/* Reset flags, just in case, for later calls */
LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
Mount *mount = MOUNT(u);
mount->is_mounted = mount->just_mounted = mount->just_changed = false;
}
return 0;
2010-01-29 06:04:08 +01:00
}
manager_dispatch_load_queue(m);
LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
Mount *mount = MOUNT(u);
2010-01-29 06:04:08 +01:00
if (!mount_is_mounted(mount)) {
/* A mount point is not around right now. It
* might be gone, or might never have
* existed. */
if (mount->from_proc_self_mountinfo &&
mount->parameters_proc_self_mountinfo.what) {
/* Remember that this device might just have disappeared */
if (set_ensure_allocated(&gone, &path_hash_ops) < 0 ||
set_put(gone, mount->parameters_proc_self_mountinfo.what) < 0)
log_oom(); /* we don't care too much about OOM here... */
}
2010-01-29 06:04:08 +01:00
mount->from_proc_self_mountinfo = false;
switch (mount->state) {
case MOUNT_MOUNTED:
/* This has just been unmounted by
* somebody else, follow the state
* change. */
mount->result = MOUNT_SUCCESS; /* make sure we forget any earlier umount failures */
2012-02-03 03:10:56 +01:00
mount_enter_dead(mount, MOUNT_SUCCESS);
break;
default:
break;
}
} else if (mount->just_mounted || mount->just_changed) {
/* A mount point was added or changed */
switch (mount->state) {
case MOUNT_DEAD:
case MOUNT_FAILED:
core: add "invocation ID" concept to service manager This adds a new invocation ID concept to the service manager. The invocation ID identifies each runtime cycle of a unit uniquely. A new randomized 128bit ID is generated each time a unit moves from and inactive to an activating or active state. The primary usecase for this concept is to connect the runtime data PID 1 maintains about a service with the offline data the journal stores about it. Previously we'd use the unit name plus start/stop times, which however is highly racy since the journal will generally process log data after the service already ended. The "invocation ID" kinda matches the "boot ID" concept of the Linux kernel, except that it applies to an individual unit instead of the whole system. The invocation ID is passed to the activated processes as environment variable. It is additionally stored as extended attribute on the cgroup of the unit. The latter is used by journald to automatically retrieve it for each log logged message and attach it to the log entry. The environment variable is very easily accessible, even for unprivileged services. OTOH the extended attribute is only accessible to privileged processes (this is because cgroupfs only supports the "trusted." xattr namespace, not "user."). The environment variable may be altered by services, the extended attribute may not be, hence is the better choice for the journal. Note that reading the invocation ID off the extended attribute from journald is racy, similar to the way reading the unit name for a logging process is. This patch adds APIs to read the invocation ID to sd-id128: sd_id128_get_invocation() may be used in a similar fashion to sd_id128_get_boot(). PID1's own logging is updated to always include the invocation ID when it logs information about a unit. A new bus call GetUnitByInvocationID() is added that allows retrieving a bus path to a unit by its invocation ID. The bus path is built using the invocation ID, thus providing a path for referring to a unit that is valid only for the current runtime cycleof it. Outlook for the future: should the kernel eventually allow passing of cgroup information along AF_UNIX/SOCK_DGRAM messages via a unique cgroup id, then we can alter the invocation ID to be generated as hash from that rather than entirely randomly. This way we can derive the invocation race-freely from the messages.
2016-08-30 23:18:46 +02:00
/* This has just been mounted by somebody else, follow the state change, but let's
* generate a new invocation ID for this implicitly and automatically. */
(void) unit_acquire_invocation_id(UNIT(mount));
2012-02-03 03:10:56 +01:00
mount_enter_mounted(mount, MOUNT_SUCCESS);
break;
case MOUNT_MOUNTING:
mount_set_state(mount, MOUNT_MOUNTING_DONE);
break;
default:
/* Nothing really changed, but let's
* issue an notification call
* nonetheless, in case somebody is
* waiting for this. (e.g. file system
* ro/rw remounts.) */
mount_set_state(mount, mount->state);
break;
}
}
if (mount_is_mounted(mount) &&
mount->from_proc_self_mountinfo &&
mount->parameters_proc_self_mountinfo.what) {
if (set_ensure_allocated(&around, &path_hash_ops) < 0 ||
set_put(around, mount->parameters_proc_self_mountinfo.what) < 0)
log_oom();
}
/* Reset the flags for later calls */
mount->is_mounted = mount->just_mounted = mount->just_changed = false;
}
SET_FOREACH(what, gone, i) {
if (set_contains(around, what))
continue;
/* Let the device units know that the device is no longer mounted */
device_found_node(m, what, 0, DEVICE_FOUND_MOUNT);
}
return 0;
}
static void mount_reset_failed(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
if (m->state == MOUNT_FAILED)
mount_set_state(m, MOUNT_DEAD);
2012-02-03 03:10:56 +01:00
m->result = MOUNT_SUCCESS;
m->reload_result = MOUNT_SUCCESS;
}
static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
mount: rework mount state engine This changes the mount unit state engine in the following ways: 1. The MOUNT_MOUNTING_SIGTERM and MOUNT_MOUNTING_SIGKILL are removed. They have been pretty much equivalent to MOUNT_UNMOUNTING_SIGTERM and MOUNT_UNMOUNTING_SIGKILL in what they do, and the outcome has been the same as well: the unit is stopped. Hence, let's simplify things a bit, and merge them. Note that we keep MOUNT_REMOUNTING_{SIGTERM|SIGKILL} however, as those states have a different outcome: the unit remains started. 2. mount_enter_signal() will now honour the SendSIGKILL= option of the mount unit if it was set. This was previously done already when we entered the signal states through a timeout, and was simply missing here. 3. A new helper function mount_enter_dead_or_mounted() is added that places the mount unit in either MOUNT_DEAD or MOUNT_MOUNTED, depending on what the kernel thinks about the mount's state. This function is called at various places now, wherever we finished an operation, and want to make sure our own state reflects again what the kernel thinks. Previously we had very similar code in a number of places and in other places didn't recheck the kernel state. Let's do that with the same logic and function at all relevant places now. 4. Rework mount_stop(): never forget about running control processes. Instead: when we have a start (i.e. a /bin/mount) process running, and are asked to stop, then enter the kill states for it, so that it gets cleaned up. This fixes #6048. Moreover, when we have a reload process running convert the possible states into the relevant unmounting states, so that we can properly execute the requested operation. Fixes #6048
2017-09-25 19:13:37 +02:00
Mount *m = MOUNT(u);
assert(m);
return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
2010-10-22 16:11:50 +02:00
}
static int mount_control_pid(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
return m->control_pid;
}
2010-04-21 03:27:44 +02:00
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
[MOUNT_EXEC_MOUNT] = "ExecMount",
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
[MOUNT_EXEC_REMOUNT] = "ExecRemount",
};
DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
2012-02-03 03:10:56 +01:00
static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
[MOUNT_SUCCESS] = "success",
[MOUNT_FAILURE_RESOURCES] = "resources",
[MOUNT_FAILURE_TIMEOUT] = "timeout",
[MOUNT_FAILURE_EXIT_CODE] = "exit-code",
[MOUNT_FAILURE_SIGNAL] = "signal",
[MOUNT_FAILURE_CORE_DUMP] = "core-dump",
[MOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[MOUNT_FAILURE_PROTOCOL] = "protocol",
2012-02-03 03:10:56 +01:00
};
DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
2010-01-26 21:39:06 +01:00
const UnitVTable mount_vtable = {
.object_size = sizeof(Mount),
.exec_context_offset = offsetof(Mount, exec_context),
.cgroup_context_offset = offsetof(Mount, cgroup_context),
.kill_context_offset = offsetof(Mount, kill_context),
.exec_runtime_offset = offsetof(Mount, exec_runtime),
.dynamic_creds_offset = offsetof(Mount, dynamic_creds),
.sections =
"Unit\0"
"Mount\0"
"Install\0",
.private_section = "Mount",
.init = mount_init,
.load = mount_load,
.done = mount_done,
2010-01-29 03:18:09 +01:00
.coldplug = mount_coldplug,
.dump = mount_dump,
.start = mount_start,
.stop = mount_stop,
.reload = mount_reload,
2010-10-22 16:11:50 +02:00
.kill = mount_kill,
2010-04-21 03:27:44 +02:00
.serialize = mount_serialize,
.deserialize_item = mount_deserialize_item,
2010-01-29 03:18:09 +01:00
.active_state = mount_active_state,
.sub_state_to_string = mount_sub_state_to_string,
2010-01-29 02:07:41 +01:00
.may_gc = mount_may_gc,
.sigchld_event = mount_sigchld_event,
.reset_failed = mount_reset_failed,
.control_pid = mount_control_pid,
.bus_vtable = bus_mount_vtable,
.bus_set_property = bus_mount_set_property,
.bus_commit_properties = bus_mount_commit_properties,
2010-04-18 03:08:16 +02:00
.get_timeout = mount_get_timeout,
.can_transient = true,
.enumerate_perpetual = mount_enumerate_perpetual,
2010-01-29 03:18:09 +01:00
.enumerate = mount_enumerate,
.shutdown = mount_shutdown,
.status_message_formats = {
.starting_stopping = {
[0] = "Mounting %s...",
[1] = "Unmounting %s...",
},
.finished_start_job = {
[JOB_DONE] = "Mounted %s.",
[JOB_FAILED] = "Failed to mount %s.",
[JOB_TIMEOUT] = "Timed out mounting %s.",
},
.finished_stop_job = {
[JOB_DONE] = "Unmounted %s.",
[JOB_FAILED] = "Failed unmounting %s.",
[JOB_TIMEOUT] = "Timed out unmounting %s.",
},
},
};