static bool automount_check_gc(Unit *u) { assert(u); if (!UNIT_TRIGGER(u)) return false; return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u)); }
static int automount_start(Unit *u) { Automount *a = AUTOMOUNT(u); Unit *trigger; int r; assert(a); assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED); if (path_is_mount_point(a->where, NULL, 0) > 0) { log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where); return -EEXIST; } trigger = UNIT_TRIGGER(u); if (!trigger || trigger->load_state != UNIT_LOADED) { log_unit_error(u, "Refusing to start, unit to trigger not loaded."); return -ENOENT; } r = unit_start_limit_test(u); if (r < 0) { automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT); return r; } r = unit_acquire_invocation_id(u); if (r < 0) return r; a->result = AUTOMOUNT_SUCCESS; automount_enter_waiting(a); return 1; }
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); }
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); }
static int automount_start(Unit *u) { Automount *a = AUTOMOUNT(u); assert(a); assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED); if (path_is_mount_point(a->where, 0) > 0) { log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where); return -EEXIST; } if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED) return -ENOENT; a->result = AUTOMOUNT_SUCCESS; automount_enter_waiting(a); return 1; }
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; }