Example #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);
}
Example #2
0
static void busname_enter_running(BusName *n) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        bool pending = false;
        Unit *other;
        Iterator i;
        int r;

        assert(n);

        if (!n->activating)
                return;

        /* We don't take connections anymore if we are supposed to
         * shut down anyway */

        if (unit_stop_pending(UNIT(n))) {
                log_unit_debug(UNIT(n), "Suppressing activation request since unit stop is scheduled.");

                /* Flush all queued activation reqeuest by closing and reopening the connection */
                bus_kernel_drop_one(n->starter_fd);

                busname_enter_listening(n);
                return;
        }

        /* If there's already a start pending don't bother to do
         * anything */
        SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
                if (unit_active_or_pending(other)) {
                        pending = true;
                        break;
                }

        if (!pending) {
                if (!UNIT_ISSET(n->service)) {
                        log_unit_error(UNIT(n), "Service to activate vanished, refusing activation.");
                        r = -ENOENT;
                        goto fail;
                }

                r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, &error, NULL);
                if (r < 0)
                        goto fail;
        }

        busname_set_state(n, BUSNAME_RUNNING);
        return;

fail:
        log_unit_warning(UNIT(n), "Failed to queue service startup job: %s", bus_error_message(&error, r));
        busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
}
Example #3
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_debug_unit(UNIT(a)->id,
                               "Suppressing automount request on %s since unit stop is scheduled.", UNIT(a)->id);
                automount_send_ready(a, -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_warning_unit(UNIT(a)->id,
                                 "%s failed to stat automount point: %m", UNIT(a)->id);
                goto fail;
        }

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

        automount_set_state(a, AUTOMOUNT_RUNNING);
        return;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
Example #4
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;
}
Example #5
0
int main(int argc, char *argv[]) {
        _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
        Manager *m = NULL;
        Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL;
        FILE *serial = NULL;
        FDSet *fdset = NULL;
        Job *j;
        int r;

        /* prepare the test */
        assert_se(set_unit_path(TEST_DIR) >= 0);
        r = manager_new(MANAGER_USER, true, &m);
        if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT, -ENOEXEC)) {
                printf("Skipping test: manager_new: %s", strerror(-r));
                return EXIT_TEST_SKIP;
        }
        assert_se(r >= 0);
        assert_se(manager_startup(m, serial, fdset) >= 0);

        printf("Load1:\n");
        assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);
        assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0);
        assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test1: (Trivial)\n");
        r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j);
        if (sd_bus_error_is_set(&err))
                log_error("error: %s: %s", err.name, err.message);
        assert_se(r == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Load2:\n");
        manager_clear_jobs(m);
        assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0);
        assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test2: (Cyclic Order, Unfixable)\n");
        assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
        assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test4: (Identical transaction)\n");
        assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Load3:\n");
        assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test5: (Colliding transaction, fail)\n");
        assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK);

        printf("Test6: (Colliding transaction, replace)\n");
        assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test7: (Unmergeable job type, fail)\n");
        assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK);

        printf("Test8: (Mergeable job type, fail)\n");
        assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test9: (Unmergeable job type, replace)\n");
        assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Load4:\n");
        assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
        assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        manager_free(m);

        return 0;
}
Example #6
0
int main(int argc, char *argv[]) {
        Manager *m = NULL;
        Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, *h = NULL;
        Job *j;

        assert_se(set_unit_path("test") >= 0);

        assert_se(manager_new(MANAGER_SYSTEM, &m) >= 0);

        printf("Load1:\n");
        assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0);
        assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0);
        assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test1: (Trivial)\n");
        assert_se(manager_add_job(m, JOB_START, c, JOB_REPLACE, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Load2:\n");
        manager_clear_jobs(m);
        assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0);
        assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test2: (Cyclic Order, Unfixable)\n");
        assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, false, NULL, &j) == -ENOEXEC);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
        assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test4: (Identical transaction)\n");
        assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Load3:\n");
        assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test5: (Colliding transaction, fail)\n");
        assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, false, NULL, &j) == -EEXIST);

        printf("Test6: (Colliding transaction, replace)\n");
        assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test7: (Unmergeable job type, fail)\n");
        assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, false, NULL, &j) == -EEXIST);

        printf("Test8: (Mergeable job type, fail)\n");
        assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Test9: (Unmergeable job type, replace)\n");
        assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        printf("Load4:\n");
        assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0);
        manager_dump_units(m, stdout, "\t");

        printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
        assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, false, NULL, &j) == 0);
        manager_dump_jobs(m, stdout, "\t");

        manager_free(m);

        return 0;
}