mirror of
https://github.com/systemd/systemd.git
synced 2024-11-28 12:53:36 +08:00
Merge pull request #3170 from poettering/v230-preparation-fixes
make virtualization detection quieter, rework unit start limit logic, detect unit file drop-in changes correctly, fix autofs state propagation
This commit is contained in:
commit
1ed7ebcfca
@ -770,7 +770,9 @@
|
||||
<command>systemctl reset-failed</command> will cause the restart rate counter for a service to be flushed,
|
||||
which is useful if the administrator wants to manually start a unit and the start limit interferes with
|
||||
that. Note that this rate-limiting is enforced after any unit condition checks are executed, and hence unit
|
||||
activations with failing conditions are not counted by this rate limiting.</para></listitem>
|
||||
activations with failing conditions are not counted by this rate limiting. Slice, target, device and scope
|
||||
units do not enforce this setting, as they are unit types whose activation may either never fail, or may
|
||||
succeed only a single time.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -280,7 +280,7 @@ static int detect_vm_uml(void) {
|
||||
return VIRTUALIZATION_UML;
|
||||
}
|
||||
|
||||
log_debug("No virtualization found in /proc/cpuinfo (%s)", cpuinfo_contents);
|
||||
log_debug("No virtualization found in /proc/cpuinfo.");
|
||||
return VIRTUALIZATION_NONE;
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,9 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
|
||||
|
||||
static int open_dev_autofs(Manager *m);
|
||||
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
|
||||
static int automount_start_expire(Automount *a);
|
||||
static void automount_stop_expire(Automount *a);
|
||||
static int automount_send_ready(Automount *a, Set *tokens, int status);
|
||||
|
||||
static void automount_init(Unit *u) {
|
||||
Automount *a = AUTOMOUNT(u);
|
||||
@ -87,8 +90,6 @@ static void automount_init(Unit *u) {
|
||||
UNIT(a)->ignore_on_isolate = true;
|
||||
}
|
||||
|
||||
static int automount_send_ready(Automount *a, Set *tokens, int status);
|
||||
|
||||
static void unmount_autofs(Automount *a) {
|
||||
int r;
|
||||
|
||||
@ -235,6 +236,9 @@ static void automount_set_state(Automount *a, AutomountState state) {
|
||||
old_state = a->state;
|
||||
a->state = state;
|
||||
|
||||
if (state != AUTOMOUNT_RUNNING)
|
||||
automount_stop_expire(a);
|
||||
|
||||
if (state != AUTOMOUNT_WAITING &&
|
||||
state != AUTOMOUNT_RUNNING)
|
||||
unmount_autofs(a);
|
||||
@ -408,7 +412,7 @@ static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, in
|
||||
init_autofs_dev_ioctl(¶m);
|
||||
param.ioctlfd = ioctl_fd;
|
||||
|
||||
if (status) {
|
||||
if (status != 0) {
|
||||
param.fail.token = token;
|
||||
param.fail.status = status;
|
||||
} else
|
||||
@ -435,7 +439,7 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) {
|
||||
if (ioctl_fd < 0)
|
||||
return ioctl_fd;
|
||||
|
||||
if (status)
|
||||
if (status != 0)
|
||||
log_unit_debug_errno(UNIT(a), status, "Sending failure: %m");
|
||||
else
|
||||
log_unit_debug(UNIT(a), "Sending success.");
|
||||
@ -462,59 +466,54 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int automount_start_expire(Automount *a);
|
||||
|
||||
int automount_update_mount(Automount *a, MountState old_state, MountState state) {
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
automount_set_state(a, AUTOMOUNT_RUNNING);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/* 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)) {
|
||||
|
||||
return 0;
|
||||
(void) automount_send_ready(a, a->tokens, -ENODEV);
|
||||
|
||||
automount_set_state(a, AUTOMOUNT_WAITING);
|
||||
}
|
||||
}
|
||||
|
||||
static void automount_enter_waiting(Automount *a) {
|
||||
@ -699,6 +698,15 @@ static int automount_start_expire(Automount *a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void automount_stop_expire(Automount *a) {
|
||||
assert(a);
|
||||
|
||||
if (!a->expire_event_source)
|
||||
return;
|
||||
|
||||
(void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
|
||||
}
|
||||
|
||||
static void automount_enter_runnning(Automount *a) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
struct stat st;
|
||||
@ -751,6 +759,7 @@ fail:
|
||||
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);
|
||||
@ -766,6 +775,12 @@ static int automount_start(Unit *u) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
a->result = AUTOMOUNT_SUCCESS;
|
||||
automount_enter_waiting(a);
|
||||
return 1;
|
||||
@ -958,7 +973,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
|
||||
case autofs_ptype_expire_direct:
|
||||
log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);
|
||||
|
||||
(void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
|
||||
automount_stop_expire(a);
|
||||
|
||||
r = set_ensure_allocated(&a->expire_tokens, NULL);
|
||||
if (r < 0) {
|
||||
@ -1037,7 +1052,9 @@ static bool automount_supported(void) {
|
||||
|
||||
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
||||
[AUTOMOUNT_SUCCESS] = "success",
|
||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources"
|
||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
||||
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
|
||||
@ -1069,6 +1086,8 @@ const UnitVTable automount_vtable = {
|
||||
|
||||
.check_gc = automount_check_gc,
|
||||
|
||||
.trigger_notify = automount_trigger_notify,
|
||||
|
||||
.reset_failed = automount_reset_failed,
|
||||
|
||||
.bus_vtable = bus_automount_vtable,
|
||||
|
@ -26,6 +26,8 @@ typedef struct Automount Automount;
|
||||
typedef enum AutomountResult {
|
||||
AUTOMOUNT_SUCCESS,
|
||||
AUTOMOUNT_FAILURE_RESOURCES,
|
||||
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
|
||||
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
|
||||
_AUTOMOUNT_RESULT_MAX,
|
||||
_AUTOMOUNT_RESULT_INVALID = -1
|
||||
} AutomountResult;
|
||||
@ -53,7 +55,5 @@ struct Automount {
|
||||
|
||||
extern const UnitVTable automount_vtable;
|
||||
|
||||
int automount_update_mount(Automount *a, MountState old_state, MountState state);
|
||||
|
||||
const char* automount_result_to_string(AutomountResult i) _const_;
|
||||
AutomountResult automount_result_from_string(const char *s) _pure_;
|
||||
|
@ -607,6 +607,7 @@ fail:
|
||||
|
||||
static int busname_start(Unit *u) {
|
||||
BusName *n = BUSNAME(u);
|
||||
int r;
|
||||
|
||||
assert(n);
|
||||
|
||||
@ -632,6 +633,12 @@ static int busname_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
busname_enter_dead(n, BUSNAME_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
n->result = BUSNAME_SUCCESS;
|
||||
busname_enter_making(n);
|
||||
|
||||
@ -1014,6 +1021,7 @@ static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
|
||||
[BUSNAME_FAILURE_EXIT_CODE] = "exit-code",
|
||||
[BUSNAME_FAILURE_SIGNAL] = "signal",
|
||||
[BUSNAME_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[BUSNAME_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@ typedef enum BusNameResult {
|
||||
BUSNAME_FAILURE_EXIT_CODE,
|
||||
BUSNAME_FAILURE_SIGNAL,
|
||||
BUSNAME_FAILURE_CORE_DUMP,
|
||||
BUSNAME_FAILURE_START_LIMIT_HIT,
|
||||
BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT,
|
||||
_BUSNAME_RESULT_MAX,
|
||||
_BUSNAME_RESULT_INVALID = -1
|
||||
|
@ -584,23 +584,6 @@ static int mount_load(Unit *u) {
|
||||
return mount_verify(m);
|
||||
}
|
||||
|
||||
static int mount_notify_automount(Mount *m, MountState old_state, MountState state) {
|
||||
Unit *p;
|
||||
int r;
|
||||
Iterator i;
|
||||
|
||||
assert(m);
|
||||
|
||||
SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
|
||||
if (p->type == UNIT_AUTOMOUNT) {
|
||||
r = automount_update_mount(AUTOMOUNT(p), old_state, state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mount_set_state(Mount *m, MountState state) {
|
||||
MountState old_state;
|
||||
assert(m);
|
||||
@ -624,8 +607,6 @@ static void mount_set_state(Mount *m, MountState state) {
|
||||
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
|
||||
}
|
||||
|
||||
mount_notify_automount(m, old_state, state);
|
||||
|
||||
if (state != old_state)
|
||||
log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state));
|
||||
|
||||
@ -984,6 +965,7 @@ fail:
|
||||
|
||||
static int mount_start(Unit *u) {
|
||||
Mount *m = MOUNT(u);
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -1002,6 +984,12 @@ static int mount_start(Unit *u) {
|
||||
|
||||
assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
m->result = MOUNT_SUCCESS;
|
||||
m->reload_result = MOUNT_SUCCESS;
|
||||
m->reset_cpu_usage = true;
|
||||
@ -1821,7 +1809,8 @@ static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
|
||||
[MOUNT_FAILURE_TIMEOUT] = "timeout",
|
||||
[MOUNT_FAILURE_EXIT_CODE] = "exit-code",
|
||||
[MOUNT_FAILURE_SIGNAL] = "signal",
|
||||
[MOUNT_FAILURE_CORE_DUMP] = "core-dump"
|
||||
[MOUNT_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[MOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
|
||||
|
@ -39,6 +39,7 @@ typedef enum MountResult {
|
||||
MOUNT_FAILURE_EXIT_CODE,
|
||||
MOUNT_FAILURE_SIGNAL,
|
||||
MOUNT_FAILURE_CORE_DUMP,
|
||||
MOUNT_FAILURE_START_LIMIT_HIT,
|
||||
_MOUNT_RESULT_MAX,
|
||||
_MOUNT_RESULT_INVALID = -1
|
||||
} MountResult;
|
||||
|
@ -560,6 +560,7 @@ static void path_mkdir(Path *p) {
|
||||
static int path_start(Unit *u) {
|
||||
Path *p = PATH(u);
|
||||
Unit *trigger;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
assert(p->state == PATH_DEAD || p->state == PATH_FAILED);
|
||||
@ -570,6 +571,12 @@ static int path_start(Unit *u) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
path_mkdir(p);
|
||||
|
||||
p->result = PATH_SUCCESS;
|
||||
@ -739,6 +746,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
|
||||
static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
||||
[PATH_SUCCESS] = "success",
|
||||
[PATH_FAILURE_RESOURCES] = "resources",
|
||||
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
||||
|
@ -62,6 +62,7 @@ static inline bool path_spec_owns_inotify_fd(PathSpec *s, int fd) {
|
||||
typedef enum PathResult {
|
||||
PATH_SUCCESS,
|
||||
PATH_FAILURE_RESOURCES,
|
||||
PATH_FAILURE_START_LIMIT_HIT,
|
||||
_PATH_RESULT_MAX,
|
||||
_PATH_RESULT_INVALID = -1
|
||||
} PathResult;
|
||||
|
@ -1957,6 +1957,7 @@ fail:
|
||||
|
||||
static int service_start(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
@ -1983,6 +1984,13 @@ static int service_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
|
||||
|
||||
/* Make sure we don't enter a busy loop of some kind. */
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
|
||||
return r;
|
||||
}
|
||||
|
||||
s->result = SERVICE_SUCCESS;
|
||||
s->reload_result = SERVICE_SUCCESS;
|
||||
s->main_pid_known = false;
|
||||
@ -3266,6 +3274,7 @@ static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
|
||||
[SERVICE_FAILURE_SIGNAL] = "signal",
|
||||
[SERVICE_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[SERVICE_FAILURE_WATCHDOG] = "watchdog",
|
||||
[SERVICE_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
|
||||
|
@ -86,6 +86,7 @@ typedef enum ServiceResult {
|
||||
SERVICE_FAILURE_SIGNAL,
|
||||
SERVICE_FAILURE_CORE_DUMP,
|
||||
SERVICE_FAILURE_WATCHDOG,
|
||||
SERVICE_FAILURE_START_LIMIT_HIT,
|
||||
_SERVICE_RESULT_MAX,
|
||||
_SERVICE_RESULT_INVALID = -1
|
||||
} ServiceResult;
|
||||
|
@ -2057,6 +2057,7 @@ fail:
|
||||
|
||||
static int socket_start(Unit *u) {
|
||||
Socket *s = SOCKET(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
@ -2101,6 +2102,12 @@ static int socket_start(Unit *u) {
|
||||
|
||||
assert(s->state == SOCKET_DEAD || s->state == SOCKET_FAILED);
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
s->result = SOCKET_SUCCESS;
|
||||
s->reset_cpu_usage = true;
|
||||
|
||||
@ -2735,17 +2742,26 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
|
||||
assert(u);
|
||||
assert(other);
|
||||
|
||||
/* Don't propagate state changes from the service if we are
|
||||
already down or accepting connections */
|
||||
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING) || s->accept)
|
||||
/* Filter out invocations with bogus state */
|
||||
if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
|
||||
return;
|
||||
|
||||
/* Don't propagate state changes from the service if we are already down */
|
||||
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
|
||||
return;
|
||||
|
||||
/* We don't care for the service state if we are in Accept=yes mode */
|
||||
if (s->accept)
|
||||
return;
|
||||
|
||||
/* Propagate start limit hit state */
|
||||
if (other->start_limit_hit) {
|
||||
socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
|
||||
/* Don't propagate anything if there's still a job queued */
|
||||
if (other->job)
|
||||
return;
|
||||
|
||||
if (IN_SET(SERVICE(other)->state,
|
||||
@ -2818,6 +2834,7 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
|
||||
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
|
||||
[SOCKET_FAILURE_SIGNAL] = "signal",
|
||||
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
||||
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
|
||||
};
|
||||
|
@ -52,6 +52,7 @@ typedef enum SocketResult {
|
||||
SOCKET_FAILURE_EXIT_CODE,
|
||||
SOCKET_FAILURE_SIGNAL,
|
||||
SOCKET_FAILURE_CORE_DUMP,
|
||||
SOCKET_FAILURE_START_LIMIT_HIT,
|
||||
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
|
||||
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
|
||||
_SOCKET_RESULT_MAX,
|
||||
|
@ -814,6 +814,7 @@ fail:
|
||||
|
||||
static int swap_start(Unit *u) {
|
||||
Swap *s = SWAP(u), *other;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
@ -842,6 +843,12 @@ static int swap_start(Unit *u) {
|
||||
if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
|
||||
return -EAGAIN;
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
s->result = SWAP_SUCCESS;
|
||||
s->reset_cpu_usage = true;
|
||||
|
||||
@ -1447,7 +1454,8 @@ static const char* const swap_result_table[_SWAP_RESULT_MAX] = {
|
||||
[SWAP_FAILURE_TIMEOUT] = "timeout",
|
||||
[SWAP_FAILURE_EXIT_CODE] = "exit-code",
|
||||
[SWAP_FAILURE_SIGNAL] = "signal",
|
||||
[SWAP_FAILURE_CORE_DUMP] = "core-dump"
|
||||
[SWAP_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
|
||||
|
@ -38,6 +38,7 @@ typedef enum SwapResult {
|
||||
SWAP_FAILURE_EXIT_CODE,
|
||||
SWAP_FAILURE_SIGNAL,
|
||||
SWAP_FAILURE_CORE_DUMP,
|
||||
SWAP_FAILURE_START_LIMIT_HIT,
|
||||
_SWAP_RESULT_MAX,
|
||||
_SWAP_RESULT_INVALID = -1
|
||||
} SwapResult;
|
||||
|
@ -599,6 +599,7 @@ static int timer_start(Unit *u) {
|
||||
Timer *t = TIMER(u);
|
||||
TimerValue *v;
|
||||
Unit *trigger;
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
|
||||
@ -609,6 +610,12 @@ static int timer_start(Unit *u) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0) {
|
||||
timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
t->last_trigger = DUAL_TIMESTAMP_NULL;
|
||||
|
||||
/* Reenable all timers that depend on unit activation time */
|
||||
@ -808,7 +815,8 @@ DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
|
||||
|
||||
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
|
||||
[TIMER_SUCCESS] = "success",
|
||||
[TIMER_FAILURE_RESOURCES] = "resources"
|
||||
[TIMER_FAILURE_RESOURCES] = "resources",
|
||||
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
|
||||
|
@ -48,6 +48,7 @@ typedef struct TimerValue {
|
||||
typedef enum TimerResult {
|
||||
TIMER_SUCCESS,
|
||||
TIMER_FAILURE_RESOURCES,
|
||||
TIMER_FAILURE_START_LIMIT_HIT,
|
||||
_TIMER_RESULT_MAX,
|
||||
_TIMER_RESULT_INVALID = -1
|
||||
} TimerResult;
|
||||
|
@ -1462,7 +1462,7 @@ void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) {
|
||||
unit_status_print_starting_stopping(u, t);
|
||||
}
|
||||
|
||||
static int unit_start_limit_test(Unit *u) {
|
||||
int unit_start_limit_test(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
if (ratelimit_test(&u->start_limit)) {
|
||||
@ -1488,7 +1488,6 @@ static int unit_start_limit_test(Unit *u) {
|
||||
int unit_start(Unit *u) {
|
||||
UnitActiveState state;
|
||||
Unit *following;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
@ -1541,11 +1540,6 @@ int unit_start(Unit *u) {
|
||||
if (!UNIT_VTABLE(u)->start)
|
||||
return -EBADR;
|
||||
|
||||
/* Make sure we don't enter a busy loop of some kind. */
|
||||
r = unit_start_limit_test(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We don't suppress calls to ->start() here when we are
|
||||
* already starting, to allow this request to be used as a
|
||||
* "hurry up" call, for example when the unit is in some "auto
|
||||
@ -2951,7 +2945,7 @@ int unit_coldplug(Unit *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool fragment_mtime_changed(const char *path, usec_t mtime) {
|
||||
static bool fragment_mtime_newer(const char *path, usec_t mtime) {
|
||||
struct stat st;
|
||||
|
||||
if (!path)
|
||||
@ -2963,7 +2957,7 @@ static bool fragment_mtime_changed(const char *path, usec_t mtime) {
|
||||
|
||||
if (mtime > 0)
|
||||
/* For non-empty files check the mtime */
|
||||
return timespec_load(&st.st_mtim) != mtime;
|
||||
return timespec_load(&st.st_mtim) > mtime;
|
||||
else if (!null_or_empty(&st))
|
||||
/* For masked files check if they are still so */
|
||||
return true;
|
||||
@ -2974,33 +2968,25 @@ static bool fragment_mtime_changed(const char *path, usec_t mtime) {
|
||||
bool unit_need_daemon_reload(Unit *u) {
|
||||
_cleanup_strv_free_ char **t = NULL;
|
||||
char **path;
|
||||
unsigned loaded_cnt, current_cnt;
|
||||
|
||||
assert(u);
|
||||
|
||||
if (fragment_mtime_changed(u->fragment_path, u->fragment_mtime) ||
|
||||
fragment_mtime_changed(u->source_path, u->source_mtime))
|
||||
if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime))
|
||||
return true;
|
||||
|
||||
if (fragment_mtime_newer(u->source_path, u->source_mtime))
|
||||
return true;
|
||||
|
||||
(void) unit_find_dropin_paths(u, &t);
|
||||
loaded_cnt = strv_length(t);
|
||||
current_cnt = strv_length(u->dropin_paths);
|
||||
if (!strv_equal(u->dropin_paths, t))
|
||||
return true;
|
||||
|
||||
if (loaded_cnt == current_cnt) {
|
||||
if (loaded_cnt == 0)
|
||||
return false;
|
||||
|
||||
if (strv_overlap(u->dropin_paths, t)) {
|
||||
STRV_FOREACH(path, u->dropin_paths)
|
||||
if (fragment_mtime_changed(*path, u->dropin_mtime))
|
||||
if (fragment_mtime_newer(*path, u->dropin_mtime))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void unit_reset_failed(Unit *u) {
|
||||
assert(u);
|
||||
|
@ -611,6 +611,8 @@ static inline bool unit_supported(Unit *u) {
|
||||
void unit_warn_if_dir_nonempty(Unit *u, const char* where);
|
||||
int unit_fail_if_symlink(Unit *u, const char* where);
|
||||
|
||||
int unit_start_limit_test(Unit *u);
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
#define log_unit_full(unit, level, error, ...) \
|
||||
|
@ -379,6 +379,7 @@ static int add_mount(
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Automount]\n"
|
||||
"Where=%s\n",
|
||||
where);
|
||||
|
@ -2334,6 +2334,8 @@ static int need_daemon_reload(sd_bus *bus, const char *unit) {
|
||||
}
|
||||
|
||||
static void warn_unit_file_changed(const char *name) {
|
||||
assert(name);
|
||||
|
||||
log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
|
||||
ansi_highlight_red(),
|
||||
ansi_normal(),
|
||||
|
Loading…
Reference in New Issue
Block a user