コード例 #1
0
ファイル: automount.c プロジェクト: aulanov/systemd
static void automount_enter_waiting(Automount *a) {
        _cleanup_close_ int ioctl_fd = -1;
        int p[2] = { -1, -1 };
        char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
        char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
                     + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
        bool mounted = false;
        int r, dev_autofs_fd;
        struct stat st;

        assert(a);
        assert(a->pipe_fd < 0);
        assert(a->where);

        set_clear(a->tokens);

        r = unit_fail_if_symlink(UNIT(a), a->where);
        if (r < 0)
                goto fail;

        (void) mkdir_p_label(a->where, 0555);

        unit_warn_if_dir_nonempty(UNIT(a), a->where);

        dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
        if (dev_autofs_fd < 0) {
                r = dev_autofs_fd;
                goto fail;
        }

        if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
                r = -errno;
                goto fail;
        }

        xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
        xsprintf(name, "systemd-"PID_FMT, getpid());
        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        p[1] = safe_close(p[1]);

        if (stat(a->where, &st) < 0) {
                r = -errno;
                goto fail;
        }

        ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
        if (ioctl_fd < 0) {
                r = ioctl_fd;
                goto fail;
        }

        r = autofs_protocol(dev_autofs_fd, ioctl_fd);
        if (r < 0)
                goto fail;

        r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
        if (r < 0)
                goto fail;

        /* Autofs fun fact:
         *
         * Unless we close the ioctl fd here, for some weird reason
         * the direct mount will not receive events from the
         * kernel. */

        r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
        if (r < 0)
                goto fail;

        (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");

        a->pipe_fd = p[0];
        a->dev_id = st.st_dev;

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");

        safe_close_pair(p);

        if (mounted) {
                r = repeat_unmount(a->where, MNT_DETACH);
                if (r < 0)
                        log_error_errno(r, "Failed to unmount, ignoring: %m");
        }

        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
コード例 #2
0
ファイル: automount.c プロジェクト: ariscop/systemd
static void automount_enter_waiting(Automount *a) {
        int p[2] = { -1, -1 };
        char name[32], options[128];
        bool mounted = false;
        int r, ioctl_fd = -1, dev_autofs_fd;
        struct stat st;

        assert(a);
        assert(a->pipe_fd < 0);
        assert(a->where);

        if (a->tokens)
                set_clear(a->tokens);

        dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
        if (dev_autofs_fd < 0) {
                r = dev_autofs_fd;
                goto fail;
        }

        /* We knowingly ignore the results of this call */
        mkdir_p_label(a->where, 0555);

        warn_if_dir_nonempty(a->meta.id, a->where);

        if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
                r = -errno;
                goto fail;
        }

        snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
        char_array_0(options);

        snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
        char_array_0(name);

        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        close_nointr_nofail(p[1]);
        p[1] = -1;

        if (stat(a->where, &st) < 0) {
                r = -errno;
                goto fail;
        }

        ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
        if (ioctl_fd < 0) {
                r = ioctl_fd;
                goto fail;
        }

        r = autofs_protocol(dev_autofs_fd, ioctl_fd);
        if (r < 0)
                goto fail;

        r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, 300);
        if (r < 0)
                goto fail;

        /* Autofs fun fact:
         *
         * Unless we close the ioctl fd here, for some weird reason
         * the direct mount will not receive events from the
         * kernel. */

        close_nointr_nofail(ioctl_fd);
        ioctl_fd = -1;

        r = sd_event_add_io(UNIT(a)->manager->event, p[0], EPOLLIN, automount_dispatch_io, a, &a->pipe_event_source);
        if (r < 0)
                goto fail;

        a->pipe_fd = p[0];
        a->dev_id = st.st_dev;

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        assert_se(close_pipe(p) == 0);

        if (ioctl_fd >= 0)
                close_nointr_nofail(ioctl_fd);

        if (mounted)
                repeat_unmount(a->where);

        log_error_unit(UNIT(a)->id,
                       "Failed to initialize automounter: %s", strerror(-r));
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}