automount.c revision 5f8ae398ae2ff71aacd85663e30eebb4ce0078f4
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering This file is part of systemd.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Copyright 2010 Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering systemd is free software; you can redistribute it and/or modify it
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering under the terms of the GNU Lesser General Public License as published by
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering (at your option) any later version.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering systemd is distributed in the hope that it will be useful, but
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Lesser General Public License for more details.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering You should have received a copy of the GNU Lesser General Public License
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic inline void expire_data_free(struct expire_data *data) {
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic void repeat_unmount(const char *path) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* If there are multiple mounts on a mount point, this
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering * removes them all */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_error_errno(errno, "Failed to unmount: %m");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int automount_send_ready(Automount *a, Set *tokens, int status);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic void unmount_autofs(Automount *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering automount_send_ready(a, a->tokens, -EHOSTDOWN);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* If we reload/reexecute things we keep the mount point
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering a->expire_event_source = sd_event_source_unref(a->expire_event_source);
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poetteringstatic int automount_add_mount_links(Automount *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return unit_require_mounts_for(UNIT(a), parent);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int automount_add_default_dependencies(Automount *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (UNIT(a)->manager->running_as != MANAGER_SYSTEM)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int automount_verify(Automount *a) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing.");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = unit_name_from_path(a->where, ".automount", &e);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing.");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* Load a .automount file */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = unit_load_fragment_and_dropin_optional(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = unit_load_related_unit(u, ".mount", &x);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = automount_add_default_dependencies(a);
b914e211f3a40f507b3cdc572838ec7f3fd5e4cfLennart Poetteringstatic void automount_set_state(Automount *a, AutomountState state) {
b914e211f3a40f507b3cdc572838ec7f3fd5e4cfLennart Poettering log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state));
b914e211f3a40f507b3cdc572838ec7f3fd5e4cfLennart Poettering unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
b914e211f3a40f507b3cdc572838ec7f3fd5e4cfLennart Poettering if (a->deserialized_state == AUTOMOUNT_WAITING ||
b914e211f3a40f507b3cdc572838ec7f3fd5e4cfLennart Poettering a->deserialized_state == AUTOMOUNT_RUNNING) {
b914e211f3a40f507b3cdc572838ec7f3fd5e4cfLennart Poettering r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
assert(a);
fprintf(f,
assert(a);
if (f != AUTOMOUNT_SUCCESS)
a->result = f;
assert(m);
if (m->dev_autofs_fd >= 0)
return m->dev_autofs_fd;
if (m->dev_autofs_fd < 0)
return -errno;
return m->dev_autofs_fd;
size_t l;
return -errno;
return -EIO;
return -errno;
return -errno;
return -errno;
if (status) {
return -errno;
unsigned token;
assert(a);
if (ioctl_fd < 0)
return ioctl_fd;
if (status)
status);
assert(a);
switch (state) {
case MOUNT_MOUNTED:
case MOUNT_REMOUNTING:
case MOUNT_DEAD:
case MOUNT_UNMOUNTING:
case MOUNT_MOUNTING_SIGTERM:
case MOUNT_MOUNTING_SIGKILL:
case MOUNT_REMOUNTING_SIGTERM:
case MOUNT_REMOUNTING_SIGKILL:
case MOUNT_UNMOUNTING_SIGTERM:
case MOUNT_UNMOUNTING_SIGKILL:
case MOUNT_FAILED:
switch (state) {
case MOUNT_DEAD:
case MOUNT_MOUNTING:
case MOUNT_MOUNTING_DONE:
case MOUNT_MOUNTING_SIGTERM:
case MOUNT_MOUNTING_SIGKILL:
case MOUNT_REMOUNTING_SIGTERM:
case MOUNT_REMOUNTING_SIGKILL:
case MOUNT_UNMOUNTING_SIGTERM:
case MOUNT_UNMOUNTING_SIGKILL:
case MOUNT_FAILED:
bool mounted = false;
int r, dev_autofs_fd;
assert(a);
goto fail;
if (dev_autofs_fd < 0) {
r = dev_autofs_fd;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
mounted = true;
r = -errno;
goto fail;
if (ioctl_fd < 0) {
r = ioctl_fd;
goto fail;
goto fail;
goto fail;
r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
goto fail;
a->pipe_fd = p[0];
fail:
safe_close_pair(p);
if (mounted)
static void *expire_thread(void *p) {
return NULL;
assert(a);
if (!data)
return log_oom();
return automount_start_expire(a);
assert(a);
if (a->timeout_idle_usec == 0)
if (a->expire_event_source) {
r = sd_event_add_time(
&a->expire_event_source,
assert(a);
goto fail;
goto fail;
r = automount_start_expire(a);
fail:
assert(a);
return -EEXIST;
return -ENOENT;
assert(a);
Iterator i;
assert(a);
assert(f);
if (a->pipe_fd >= 0) {
int copy;
if (copy < 0)
return copy;
assert(a);
if (state < 0)
else if (f != AUTOMOUNT_SUCCESS)
a->result = f;
a->dev_id = (unsigned) d;
unsigned token;
log_oom();
unsigned token;
log_oom();
int fd;
assert(u);
assert(u);
assert(u);
if (!UNIT_TRIGGER(u))
assert(a);
goto fail;
goto fail;
log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
goto fail;
fail:
assert(m);
assert(a);
static bool automount_supported(void) {
if (supported < 0)
return supported;
.sections =
.no_alias = true,
.no_instances = true,
.finished_start_job = {
.finished_stop_job = {