Exemple #1
0
static void automount_enter_running(Automount *a) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        Unit *trigger;
        struct stat st;
        int r;

        assert(a);

        /* If the user masked our unit in the meantime, fail */
        if (UNIT(a)->load_state != UNIT_LOADED) {
                log_unit_error(UNIT(a), "Suppressing automount event since unit is no longer loaded.");
                goto fail;
        }

        /* We don't take mount requests anymore if we are supposed to
         * shut down anyway */
        if (unit_stop_pending(UNIT(a))) {
                log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled.");
                automount_send_ready(a, a->tokens, -EHOSTDOWN);
                automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
                return;
        }

        mkdir_p_label(a->where, a->directory_mode);

        /* Before we do anything, let's see if somebody is playing games with us? */
        if (lstat(a->where, &st) < 0) {
                log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
                goto fail;
        }

        /* The mount unit may have been explicitly started before we got the
         * autofs request. Ack it to unblock anything waiting on the mount point. */
        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) {
                log_unit_info(UNIT(a), "Automount point already active?");
                automount_send_ready(a, a->tokens, 0);
                return;
        }

        trigger = UNIT_TRIGGER(UNIT(a));
        if (!trigger) {
                log_unit_error(UNIT(a), "Unit to trigger vanished.");
                goto fail;
        }

        r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
        if (r < 0) {
                log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
                goto fail;
        }

        automount_set_state(a, AUTOMOUNT_RUNNING);
        return;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
Exemple #2
0
int automount_update_mount(Automount *a, MountState old_state, MountState state) {
        int r;

        assert(a);

        switch (state) {
        case MOUNT_MOUNTED:
        case MOUNT_REMOUNTING:
                automount_send_ready(a, a->tokens, 0);
                r = automount_start_expire(a);
                if (r < 0)
                        log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
                break;
         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:
                if (old_state != state)
                        automount_send_ready(a, a->tokens, -ENODEV);
                (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
                break;
        default:
                break;
        }

        switch (state) {
        case MOUNT_DEAD:
                automount_send_ready(a, a->expire_tokens, 0);
                break;
         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:
                if (old_state != state)
                        automount_send_ready(a, a->expire_tokens, -ENODEV);
                break;
        default:
                break;
        }

        return 0;
}
Exemple #3
0
static void unmount_autofs(Automount *a) {
        assert(a);

        if (a->pipe_fd < 0)
                return;

        automount_send_ready(a, a->tokens, -EHOSTDOWN);
        automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);

        a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
        a->pipe_fd = safe_close(a->pipe_fd);

        /* If we reload/reexecute things we keep the mount point
         * around */
        if (a->where &&
            (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
             UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
                repeat_unmount(a->where);
}
Exemple #4
0
static void automount_enter_runnning(Automount *a) {
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        struct stat st;
        int r;

        assert(a);

        /* We don't take mount requests anymore if we are supposed to
         * shut down anyway */
        if (unit_stop_pending(UNIT(a))) {
                log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled.");
                automount_send_ready(a, a->tokens, -EHOSTDOWN);
                automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
                return;
        }

        mkdir_p_label(a->where, a->directory_mode);

        /* Before we do anything, let's see if somebody is playing games with us? */
        if (lstat(a->where, &st) < 0) {
                log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
                goto fail;
        }

        if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
                log_unit_info(UNIT(a), "Automount point already active?");
        else {
                r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
                                    JOB_REPLACE, true, &error, NULL);
                if (r < 0) {
                        log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
                        goto fail;
                }
        }

        automount_set_state(a, AUTOMOUNT_RUNNING);
        return;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
Exemple #5
0
static void unmount_autofs(Automount *a) {
        int r;

        assert(a);

        if (a->pipe_fd < 0)
                return;

        a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
        a->pipe_fd = safe_close(a->pipe_fd);

        /* If we reload/reexecute things we keep the mount point around */
        if (!IN_SET(UNIT(a)->manager->exit_code, MANAGER_RELOAD, MANAGER_REEXECUTE)) {

                automount_send_ready(a, a->tokens, -EHOSTDOWN);
                automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);

                if (a->where) {
                        r = repeat_unmount(a->where, MNT_DETACH);
                        if (r < 0)
                                log_error_errno(r, "Failed to unmount: %m");
                }
        }
}
Exemple #6
0
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        union autofs_v5_packet_union packet;
        Automount *a = AUTOMOUNT(userdata);
        struct stat st;
        Unit *trigger;
        int r;

        assert(a);
        assert(fd == a->pipe_fd);

        if (events != EPOLLIN) {
                log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
                goto fail;
        }

        r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
        if (r < 0) {
                log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
                goto fail;
        }

        switch (packet.hdr.type) {

        case autofs_ptype_missing_direct:

                if (packet.v5_packet.pid > 0) {
                        _cleanup_free_ char *p = NULL;

                        get_process_comm(packet.v5_packet.pid, &p);
                        log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
                } else
                        log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);

                r = set_ensure_allocated(&a->tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                automount_enter_runnning(a);
                break;

        case autofs_ptype_expire_direct:
                log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);

                automount_stop_expire(a);

                r = set_ensure_allocated(&a->expire_tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                /* Before we do anything, let's see if somebody is playing games with us? */
                if (lstat(a->where, &st) < 0) {
                        log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
                        goto fail;
                }

                if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
                        log_unit_info(UNIT(a), "Automount point already unmounted?");
                        automount_send_ready(a, a->expire_tokens, 0);
                        break;
                }

                trigger = UNIT_TRIGGER(UNIT(a));
                if (!trigger) {
                        log_unit_error(UNIT(a), "Unit to trigger vanished.");
                        goto fail;
                }

                r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
                if (r < 0) {
                        log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
                        goto fail;
                }
                break;

        default:
                log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
                break;
        }

        return 0;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
        return 0;
}
Exemple #7
0
static void automount_trigger_notify(Unit *u, Unit *other) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(other);

        /* Filter out invocations with bogus state */
        if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
                return;

        /* Don't propagate state changes from the mount if we are already down */
        if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
                return;

        /* Propagate start limit hit state */
        if (other->start_limit_hit) {
                automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT);
                return;
        }

        /* Don't propagate anything if there's still a job queued */
        if (other->job)
                return;

        /* The mount is successfully established */
        if (IN_SET(MOUNT(other)->state, MOUNT_MOUNTED, MOUNT_REMOUNTING)) {
                (void) automount_send_ready(a, a->tokens, 0);

                r = automount_start_expire(a);
                if (r < 0)
                        log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");

                automount_set_state(a, AUTOMOUNT_RUNNING);
        }

        if (IN_SET(MOUNT(other)->state,
                   MOUNT_MOUNTING, MOUNT_MOUNTING_DONE,
                   MOUNT_MOUNTED, MOUNT_REMOUNTING,
                   MOUNT_MOUNTING_SIGTERM, MOUNT_MOUNTING_SIGKILL,
                   MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
                   MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
                   MOUNT_FAILED)) {

                (void) automount_send_ready(a, a->expire_tokens, -ENODEV);
        }

        if (MOUNT(other)->state == MOUNT_DEAD)
                (void) automount_send_ready(a, a->expire_tokens, 0);

        /* The mount is in some unhappy state now, let's unfreeze any waiting clients */
        if (IN_SET(MOUNT(other)->state,
                   MOUNT_DEAD, MOUNT_UNMOUNTING,
                   MOUNT_MOUNTING_SIGTERM, MOUNT_MOUNTING_SIGKILL,
                   MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
                   MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
                   MOUNT_FAILED)) {

                (void) automount_send_ready(a, a->tokens, -ENODEV);

                automount_set_state(a, AUTOMOUNT_WAITING);
        }
}