mirror of
https://github.com/systemd/systemd.git
synced 2024-10-27 10:25:37 +03:00
Merge pull request #6912 from poettering/mount-kill-control
mount unit state engine fixes
This commit is contained in:
commit
9782c78794
@ -145,6 +145,7 @@ basic_sources_plain = files('''
|
||||
securebits.h
|
||||
selinux-util.c
|
||||
selinux-util.h
|
||||
set.c
|
||||
set.h
|
||||
sigbus.c
|
||||
sigbus.h
|
||||
|
61
src/basic/set.c
Normal file
61
src/basic/set.c
Normal file
@ -0,0 +1,61 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "set.h"
|
||||
|
||||
int set_make(Set **ret, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS, void *add, ...) {
|
||||
_cleanup_set_free_ Set *s = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
s = set_new(hash_ops HASHMAP_DEBUG_PASS_ARGS);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
if (add) {
|
||||
va_list ap;
|
||||
|
||||
r = set_put(s, add);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
va_start(ap, add);
|
||||
|
||||
for(;;) {
|
||||
void *arg = va_arg(ap, void*);
|
||||
|
||||
if (!arg)
|
||||
break;
|
||||
|
||||
r = set_put(s, arg);
|
||||
if (r < 0) {
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
*ret = s;
|
||||
s = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
@ -136,3 +136,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
|
||||
|
||||
#define _cleanup_set_free_ _cleanup_(set_freep)
|
||||
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
|
||||
|
||||
int set_make(Set **ret, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS, void *add, ...);
|
||||
|
@ -897,8 +897,6 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
|
||||
[MOUNT_MOUNTED] = "mounted",
|
||||
[MOUNT_REMOUNTING] = "remounting",
|
||||
[MOUNT_UNMOUNTING] = "unmounting",
|
||||
[MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
|
||||
[MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
|
||||
[MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
|
||||
[MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
|
||||
[MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
|
||||
@ -980,8 +978,6 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
|
||||
[SWAP_ACTIVATING_DONE] = "activating-done",
|
||||
[SWAP_ACTIVE] = "active",
|
||||
[SWAP_DEACTIVATING] = "deactivating",
|
||||
[SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
|
||||
[SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
|
||||
[SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
|
||||
[SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
|
||||
[SWAP_FAILED] = "failed"
|
||||
|
@ -89,8 +89,6 @@ typedef enum MountState {
|
||||
MOUNT_MOUNTED,
|
||||
MOUNT_REMOUNTING,
|
||||
MOUNT_UNMOUNTING,
|
||||
MOUNT_MOUNTING_SIGTERM,
|
||||
MOUNT_MOUNTING_SIGKILL,
|
||||
MOUNT_REMOUNTING_SIGTERM,
|
||||
MOUNT_REMOUNTING_SIGKILL,
|
||||
MOUNT_UNMOUNTING_SIGTERM,
|
||||
@ -172,8 +170,6 @@ typedef enum SwapState {
|
||||
SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
|
||||
SWAP_ACTIVE,
|
||||
SWAP_DEACTIVATING,
|
||||
SWAP_ACTIVATING_SIGTERM,
|
||||
SWAP_ACTIVATING_SIGKILL,
|
||||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL,
|
||||
SWAP_FAILED,
|
||||
|
@ -529,7 +529,6 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
|
||||
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)) {
|
||||
@ -543,7 +542,6 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
|
||||
/* 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)) {
|
||||
|
303
src/core/mount.c
303
src/core/mount.c
@ -58,8 +58,6 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
|
||||
[MOUNT_MOUNTED] = UNIT_ACTIVE,
|
||||
[MOUNT_REMOUNTING] = UNIT_RELOADING,
|
||||
[MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
|
||||
[MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
|
||||
[MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
|
||||
[MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
|
||||
@ -70,6 +68,18 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
|
||||
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
|
||||
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
|
||||
|
||||
static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
|
||||
return IN_SET(state,
|
||||
MOUNT_MOUNTING,
|
||||
MOUNT_MOUNTING_DONE,
|
||||
MOUNT_REMOUNTING,
|
||||
MOUNT_REMOUNTING_SIGTERM,
|
||||
MOUNT_REMOUNTING_SIGKILL,
|
||||
MOUNT_UNMOUNTING,
|
||||
MOUNT_UNMOUNTING_SIGTERM,
|
||||
MOUNT_UNMOUNTING_SIGKILL);
|
||||
}
|
||||
|
||||
static bool mount_needs_network(const char *options, const char *fstype) {
|
||||
if (fstab_test_option(options, "_netdev\0"))
|
||||
return true;
|
||||
@ -121,20 +131,6 @@ static bool mount_is_automount(const MountParameters *p) {
|
||||
"x-systemd.automount\0");
|
||||
}
|
||||
|
||||
static bool mount_state_active(MountState state) {
|
||||
return IN_SET(state,
|
||||
MOUNT_MOUNTING,
|
||||
MOUNT_MOUNTING_DONE,
|
||||
MOUNT_REMOUNTING,
|
||||
MOUNT_UNMOUNTING,
|
||||
MOUNT_MOUNTING_SIGTERM,
|
||||
MOUNT_MOUNTING_SIGKILL,
|
||||
MOUNT_UNMOUNTING_SIGTERM,
|
||||
MOUNT_UNMOUNTING_SIGKILL,
|
||||
MOUNT_REMOUNTING_SIGTERM,
|
||||
MOUNT_REMOUNTING_SIGKILL);
|
||||
}
|
||||
|
||||
static bool mount_is_bound_to_device(const Mount *m) {
|
||||
const MountParameters *p;
|
||||
|
||||
@ -642,7 +638,7 @@ static void mount_set_state(Mount *m, MountState state) {
|
||||
old_state = m->state;
|
||||
m->state = state;
|
||||
|
||||
if (!mount_state_active(state)) {
|
||||
if (!MOUNT_STATE_WITH_PROCESS(state)) {
|
||||
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
|
||||
mount_unwatch_control_pid(m);
|
||||
m->control_command = NULL;
|
||||
@ -653,7 +649,6 @@ static void mount_set_state(Mount *m, MountState state) {
|
||||
log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state));
|
||||
|
||||
unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
|
||||
m->reload_result = MOUNT_SUCCESS;
|
||||
}
|
||||
|
||||
static int mount_coldplug(Unit *u) {
|
||||
@ -674,7 +669,7 @@ static int mount_coldplug(Unit *u) {
|
||||
|
||||
if (m->control_pid > 0 &&
|
||||
pid_is_unwaited(m->control_pid) &&
|
||||
mount_state_active(new_state)) {
|
||||
MOUNT_STATE_WITH_PROCESS(new_state)) {
|
||||
|
||||
r = unit_watch_pid(UNIT(m), m->control_pid);
|
||||
if (r < 0)
|
||||
@ -822,6 +817,35 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
|
||||
mount_set_state(m, MOUNT_MOUNTED);
|
||||
}
|
||||
|
||||
static void mount_enter_dead_or_mounted(Mount *m, MountResult f) {
|
||||
assert(m);
|
||||
|
||||
/* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point. We use this
|
||||
* whenever we executed an operation, so that our internal state reflects what the kernel says again, after all
|
||||
* ultimately we just mirror the kernel's internal state on this. */
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, f);
|
||||
else
|
||||
mount_enter_dead(m, f);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(MountState state) {
|
||||
switch (state) {
|
||||
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
return KILL_TERMINATE;
|
||||
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
case MOUNT_UNMOUNTING_SIGKILL:
|
||||
return KILL_KILL;
|
||||
|
||||
default:
|
||||
return _KILL_OPERATION_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
|
||||
int r;
|
||||
|
||||
@ -833,8 +857,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
|
||||
r = unit_kill_context(
|
||||
UNIT(m),
|
||||
&m->kill_context,
|
||||
(state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM) ?
|
||||
KILL_KILL : KILL_TERMINATE,
|
||||
state_to_kill_operation(state),
|
||||
-1,
|
||||
m->control_pid,
|
||||
false);
|
||||
@ -847,26 +870,20 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
|
||||
goto fail;
|
||||
|
||||
mount_set_state(m, state);
|
||||
} else if (state == MOUNT_REMOUNTING_SIGTERM)
|
||||
} else if (state == MOUNT_REMOUNTING_SIGTERM && m->kill_context.send_sigkill)
|
||||
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
|
||||
else if (state == MOUNT_REMOUNTING_SIGKILL)
|
||||
else if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL))
|
||||
mount_enter_mounted(m, MOUNT_SUCCESS);
|
||||
else if (state == MOUNT_MOUNTING_SIGTERM)
|
||||
mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_SUCCESS);
|
||||
else if (state == MOUNT_UNMOUNTING_SIGTERM)
|
||||
else if (state == MOUNT_UNMOUNTING_SIGTERM && m->kill_context.send_sigkill)
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_SUCCESS);
|
||||
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m");
|
||||
|
||||
if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL))
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
|
||||
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static void mount_enter_unmounting(Mount *m) {
|
||||
@ -904,7 +921,7 @@ static void mount_enter_unmounting(Mount *m) {
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to run 'umount' task: %m");
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
|
||||
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static void mount_enter_mounting(Mount *m) {
|
||||
@ -945,7 +962,6 @@ static void mount_enter_mounting(Mount *m) {
|
||||
r = exec_command_append(m->control_command, "-o", opts, NULL);
|
||||
} else
|
||||
r = -ENOENT;
|
||||
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@ -961,7 +977,17 @@ static void mount_enter_mounting(Mount *m) {
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to run 'mount' task: %m");
|
||||
mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
|
||||
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static void mount_set_reload_result(Mount *m, MountResult result) {
|
||||
assert(m);
|
||||
|
||||
/* Only store the first error we encounter */
|
||||
if (m->reload_result != MOUNT_SUCCESS)
|
||||
return;
|
||||
|
||||
m->reload_result = result;
|
||||
}
|
||||
|
||||
static void mount_enter_remounting(Mount *m) {
|
||||
@ -970,6 +996,9 @@ static void mount_enter_remounting(Mount *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
/* Reset reload result when we are about to start a new remount operation */
|
||||
m->reload_result = MOUNT_SUCCESS;
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_REMOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
|
||||
|
||||
@ -991,7 +1020,6 @@ static void mount_enter_remounting(Mount *m) {
|
||||
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
|
||||
} else
|
||||
r = -ENOENT;
|
||||
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@ -1007,8 +1035,8 @@ static void mount_enter_remounting(Mount *m) {
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(m), r, "Failed to run 'remount' task: %m");
|
||||
m->reload_result = MOUNT_FAILURE_RESOURCES;
|
||||
mount_enter_mounted(m, MOUNT_SUCCESS);
|
||||
mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES);
|
||||
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
|
||||
}
|
||||
|
||||
static int mount_start(Unit *u) {
|
||||
@ -1022,9 +1050,7 @@ static int mount_start(Unit *u) {
|
||||
if (IN_SET(m->state,
|
||||
MOUNT_UNMOUNTING,
|
||||
MOUNT_UNMOUNTING_SIGTERM,
|
||||
MOUNT_UNMOUNTING_SIGKILL,
|
||||
MOUNT_MOUNTING_SIGTERM,
|
||||
MOUNT_MOUNTING_SIGKILL))
|
||||
MOUNT_UNMOUNTING_SIGKILL))
|
||||
return -EAGAIN;
|
||||
|
||||
/* Already on it! */
|
||||
@ -1056,25 +1082,38 @@ static int mount_stop(Unit *u) {
|
||||
|
||||
assert(m);
|
||||
|
||||
/* Already on it */
|
||||
if (IN_SET(m->state,
|
||||
MOUNT_UNMOUNTING,
|
||||
MOUNT_UNMOUNTING_SIGKILL,
|
||||
MOUNT_UNMOUNTING_SIGTERM,
|
||||
MOUNT_MOUNTING_SIGTERM,
|
||||
MOUNT_MOUNTING_SIGKILL))
|
||||
switch (m->state) {
|
||||
|
||||
case MOUNT_UNMOUNTING:
|
||||
case MOUNT_UNMOUNTING_SIGKILL:
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
/* Already on it */
|
||||
return 0;
|
||||
|
||||
assert(IN_SET(m->state,
|
||||
MOUNT_MOUNTING,
|
||||
MOUNT_MOUNTING_DONE,
|
||||
MOUNT_MOUNTED,
|
||||
MOUNT_REMOUNTING,
|
||||
MOUNT_REMOUNTING_SIGTERM,
|
||||
MOUNT_REMOUNTING_SIGKILL));
|
||||
case MOUNT_MOUNTING:
|
||||
case MOUNT_MOUNTING_DONE:
|
||||
case MOUNT_REMOUNTING:
|
||||
/* If we are still waiting for /bin/mount, we go directly into kill mode. */
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_SUCCESS);
|
||||
return 0;
|
||||
|
||||
mount_enter_unmounting(m);
|
||||
return 1;
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
/* If we are already waiting for a hung remount, convert this to the matching unmounting state */
|
||||
mount_set_state(m, MOUNT_UNMOUNTING_SIGTERM);
|
||||
return 0;
|
||||
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
/* as above */
|
||||
mount_set_state(m, MOUNT_UNMOUNTING_SIGKILL);
|
||||
return 0;
|
||||
|
||||
case MOUNT_MOUNTED:
|
||||
mount_enter_unmounting(m);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unexpected state.");
|
||||
}
|
||||
}
|
||||
|
||||
static int mount_reload(Unit *u) {
|
||||
@ -1082,12 +1121,13 @@ static int mount_reload(Unit *u) {
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->state == MOUNT_MOUNTING_DONE)
|
||||
if (m->state == MOUNT_MOUNTING_DONE) /* not yet ready to reload, try again */
|
||||
return -EAGAIN;
|
||||
|
||||
assert(m->state == MOUNT_MOUNTED);
|
||||
|
||||
mount_enter_remounting(m);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1210,7 +1250,9 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
else
|
||||
assert_not_reached("Unknown code");
|
||||
|
||||
if (m->result == MOUNT_SUCCESS)
|
||||
if (IN_SET(m->state, MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM))
|
||||
mount_set_reload_result(m, f);
|
||||
else if (m->result == MOUNT_SUCCESS)
|
||||
m->result = f;
|
||||
|
||||
if (m->control_command) {
|
||||
@ -1223,19 +1265,15 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
log_unit_full(u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
|
||||
"Mount process exited, code=%s status=%i", sigchld_code_to_string(code), status);
|
||||
|
||||
/* Note that mount(8) returning and the kernel sending us a
|
||||
* mount table change event might happen out-of-order. If an
|
||||
* operation succeed we assume the kernel will follow soon too
|
||||
* and already change into the resulting state. If it fails
|
||||
* we check if the kernel still knows about the mount. and
|
||||
* change state accordingly. */
|
||||
/* Note that mount(8) returning and the kernel sending us a mount table change event might happen
|
||||
* out-of-order. If an operation succeed we assume the kernel will follow soon too and already change into the
|
||||
* resulting state. If it fails we check if the kernel still knows about the mount. and change state
|
||||
* accordingly. */
|
||||
|
||||
switch (m->state) {
|
||||
|
||||
case MOUNT_MOUNTING:
|
||||
case MOUNT_MOUNTING_DONE:
|
||||
case MOUNT_MOUNTING_SIGKILL:
|
||||
case MOUNT_MOUNTING_SIGTERM:
|
||||
|
||||
if (f == MOUNT_SUCCESS || m->from_proc_self_mountinfo)
|
||||
/* If /bin/mount returned success, or if we see the mount point in /proc/self/mountinfo we are
|
||||
@ -1247,49 +1285,32 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
break;
|
||||
|
||||
case MOUNT_REMOUNTING:
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
|
||||
m->reload_result = f;
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_SUCCESS);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_SUCCESS);
|
||||
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
|
||||
break;
|
||||
|
||||
case MOUNT_UNMOUNTING:
|
||||
case MOUNT_UNMOUNTING_SIGKILL:
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
|
||||
if (f == MOUNT_SUCCESS) {
|
||||
if (m->from_proc_self_mountinfo) {
|
||||
|
||||
if (m->from_proc_self_mountinfo) {
|
||||
/* Still a mount point? If so, let's try again. Most likely there were multiple mount points
|
||||
* stacked on top of each other. Note that due to the io event priority logic we can be sure
|
||||
* the new mountinfo is loaded before we process the SIGCHLD for the mount command. */
|
||||
|
||||
/* Still a mount point? If so, let's
|
||||
* try again. Most likely there were
|
||||
* multiple mount points stacked on
|
||||
* top of each other. Note that due to
|
||||
* the io event priority logic we can
|
||||
* be sure the new mountinfo is loaded
|
||||
* before we process the SIGCHLD for
|
||||
* the mount command. */
|
||||
|
||||
if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
|
||||
log_unit_debug(u, "Mount still present, trying again.");
|
||||
m->n_retry_umount++;
|
||||
mount_enter_unmounting(m);
|
||||
} else {
|
||||
log_unit_debug(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount);
|
||||
mount_enter_mounted(m, f);
|
||||
}
|
||||
} else
|
||||
mount_enter_dead(m, f);
|
||||
|
||||
} else if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, f);
|
||||
else
|
||||
if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
|
||||
log_unit_debug(u, "Mount still present, trying again.");
|
||||
m->n_retry_umount++;
|
||||
mount_enter_unmounting(m);
|
||||
} else {
|
||||
log_unit_debug(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount);
|
||||
mount_enter_mounted(m, f);
|
||||
}
|
||||
} else
|
||||
mount_enter_dead(m, f);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1310,14 +1331,33 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
|
||||
|
||||
case MOUNT_MOUNTING:
|
||||
case MOUNT_MOUNTING_DONE:
|
||||
log_unit_warning(UNIT(m), "Mounting timed out. Stopping.");
|
||||
mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
|
||||
log_unit_warning(UNIT(m), "Mounting timed out. Terminating.");
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case MOUNT_REMOUNTING:
|
||||
log_unit_warning(UNIT(m), "Remounting timed out. Stopping.");
|
||||
m->reload_result = MOUNT_FAILURE_TIMEOUT;
|
||||
mount_enter_mounted(m, MOUNT_SUCCESS);
|
||||
log_unit_warning(UNIT(m), "Remounting timed out. Killing remount process.");
|
||||
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
|
||||
mount_enter_signal(m, MOUNT_REMOUNTING_SIGTERM, MOUNT_SUCCESS);
|
||||
break;
|
||||
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
|
||||
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(m), "Remounting timed out. Killing.");
|
||||
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
|
||||
} else {
|
||||
log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
|
||||
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
|
||||
|
||||
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
|
||||
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
|
||||
break;
|
||||
|
||||
case MOUNT_UNMOUNTING:
|
||||
@ -1325,57 +1365,19 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case MOUNT_MOUNTING_SIGTERM:
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(m), "Mounting timed out. Killing.");
|
||||
mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(m), "Mounting timed out. Skipping SIGKILL. Ignoring.");
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(m), "Remounting timed out. Killing.");
|
||||
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(m), "Unmounting timed out. Killing.");
|
||||
log_unit_warning(UNIT(m), "Mount process timed out. Killing.");
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(m), "Unmounting timed out. Skipping SIGKILL. Ignoring.");
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
|
||||
log_unit_warning(UNIT(m), "Mount process timed out. Skipping SIGKILL. Ignoring.");
|
||||
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOUNT_MOUNTING_SIGKILL:
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
case MOUNT_UNMOUNTING_SIGKILL:
|
||||
log_unit_warning(UNIT(m),"Mount process still around after SIGKILL. Ignoring.");
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
|
||||
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
|
||||
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1633,7 +1635,6 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
|
||||
}
|
||||
|
||||
static void mount_shutdown(Manager *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
m->mount_event_source = sd_event_source_unref(m->mount_event_source);
|
||||
@ -1904,6 +1905,10 @@ static void mount_reset_failed(Unit *u) {
|
||||
}
|
||||
|
||||
static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
|
||||
Mount *m = MOUNT(u);
|
||||
|
||||
assert(m);
|
||||
|
||||
return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
|
||||
}
|
||||
|
||||
|
@ -1631,7 +1631,6 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
||||
s->main_pid,
|
||||
s->control_pid,
|
||||
s->main_pid_alien);
|
||||
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@ -1786,13 +1785,39 @@ fail:
|
||||
}
|
||||
|
||||
static void service_kill_control_processes(Service *s) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
if (!UNIT(s)->cgroup_path)
|
||||
return;
|
||||
assert(s);
|
||||
|
||||
p = strjoina(UNIT(s)->cgroup_path, "/control");
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, CGROUP_SIGCONT|CGROUP_IGNORE_SELF|CGROUP_REMOVE, NULL, NULL, NULL);
|
||||
if (s->control_pid > 0) {
|
||||
r = kill_and_sigcont(s->control_pid, SIGKILL);
|
||||
if (r < 0) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
|
||||
(void) get_process_comm(s->control_pid, &comm);
|
||||
|
||||
log_unit_debug_errno(UNIT(s), r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m",
|
||||
s->control_pid, strna(comm));
|
||||
}
|
||||
}
|
||||
|
||||
if (UNIT(s)->cgroup_path) {
|
||||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
char *p;
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
r = set_make(&pid_set, PID_TO_PTR(s->control_pid), NULL);
|
||||
if (r < 0) {
|
||||
log_oom();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
p = strjoina(UNIT(s)->cgroup_path, "/control");
|
||||
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, CGROUP_SIGCONT|CGROUP_IGNORE_SELF|CGROUP_REMOVE, pid_set, NULL, NULL);
|
||||
if (r < 0)
|
||||
log_unit_debug_errno(UNIT(s), r, "Failed to send SIGKILL to processes of control group %s: %m", p);
|
||||
}
|
||||
}
|
||||
|
||||
static void service_enter_start(Service *s) {
|
||||
@ -3411,9 +3436,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
|
||||
}
|
||||
|
||||
if (!streq_ptr(s->status_text, t)) {
|
||||
|
||||
free_and_replace(s->status_text, t);
|
||||
|
||||
notify_dbus = true;
|
||||
}
|
||||
}
|
||||
@ -3523,10 +3546,11 @@ static void service_bus_name_owner_change(
|
||||
|
||||
} else if (new_owner &&
|
||||
s->main_pid <= 0 &&
|
||||
(s->state == SERVICE_START ||
|
||||
s->state == SERVICE_START_POST ||
|
||||
s->state == SERVICE_RUNNING ||
|
||||
s->state == SERVICE_RELOAD)) {
|
||||
IN_SET(s->state,
|
||||
SERVICE_START,
|
||||
SERVICE_START_POST,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD)) {
|
||||
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||
pid_t pid;
|
||||
@ -3609,6 +3633,8 @@ static void service_reset_failed(Unit *u) {
|
||||
static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
|
||||
Service *s = SERVICE(u);
|
||||
|
||||
assert(s);
|
||||
|
||||
return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
|
||||
}
|
||||
|
||||
|
119
src/core/swap.c
119
src/core/swap.c
@ -49,8 +49,6 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
|
||||
[SWAP_ACTIVATING_DONE] = UNIT_ACTIVE,
|
||||
[SWAP_ACTIVE] = UNIT_ACTIVE,
|
||||
[SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
|
||||
[SWAP_ACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SWAP_ACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SWAP_FAILED] = UNIT_FAILED
|
||||
@ -59,6 +57,15 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
|
||||
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
|
||||
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
|
||||
|
||||
static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
|
||||
return IN_SET(state,
|
||||
SWAP_ACTIVATING,
|
||||
SWAP_ACTIVATING_DONE,
|
||||
SWAP_DEACTIVATING,
|
||||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL);
|
||||
}
|
||||
|
||||
static void swap_unset_proc_swaps(Swap *s) {
|
||||
assert(s);
|
||||
|
||||
@ -487,14 +494,7 @@ static void swap_set_state(Swap *s, SwapState state) {
|
||||
old_state = s->state;
|
||||
s->state = state;
|
||||
|
||||
if (!IN_SET(state,
|
||||
SWAP_ACTIVATING,
|
||||
SWAP_ACTIVATING_SIGTERM,
|
||||
SWAP_ACTIVATING_SIGKILL,
|
||||
SWAP_ACTIVATING_DONE,
|
||||
SWAP_DEACTIVATING,
|
||||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL)) {
|
||||
if (!SWAP_STATE_WITH_PROCESS(state)) {
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
swap_unwatch_control_pid(s);
|
||||
s->control_command = NULL;
|
||||
@ -534,14 +534,7 @@ static int swap_coldplug(Unit *u) {
|
||||
|
||||
if (s->control_pid > 0 &&
|
||||
pid_is_unwaited(s->control_pid) &&
|
||||
IN_SET(new_state,
|
||||
SWAP_ACTIVATING,
|
||||
SWAP_ACTIVATING_SIGTERM,
|
||||
SWAP_ACTIVATING_SIGKILL,
|
||||
SWAP_ACTIVATING_DONE,
|
||||
SWAP_DEACTIVATING,
|
||||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL)) {
|
||||
SWAP_STATE_WITH_PROCESS(new_state)) {
|
||||
|
||||
r = unit_watch_pid(UNIT(s), s->control_pid);
|
||||
if (r < 0)
|
||||
@ -693,6 +686,15 @@ static void swap_enter_active(Swap *s, SwapResult f) {
|
||||
swap_set_state(s, SWAP_ACTIVE);
|
||||
}
|
||||
|
||||
static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
|
||||
assert(s);
|
||||
|
||||
if (s->from_proc_swaps)
|
||||
swap_enter_active(s, f);
|
||||
else
|
||||
swap_enter_dead(s, f);
|
||||
}
|
||||
|
||||
static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
||||
int r;
|
||||
KillOperation kop;
|
||||
@ -702,7 +704,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
||||
if (s->result == SWAP_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
if (IN_SET(state, SWAP_ACTIVATING_SIGTERM, SWAP_DEACTIVATING_SIGTERM))
|
||||
if (state == SWAP_DEACTIVATING_SIGTERM)
|
||||
kop = KILL_TERMINATE;
|
||||
else
|
||||
kop = KILL_KILL;
|
||||
@ -717,18 +719,16 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
||||
goto fail;
|
||||
|
||||
swap_set_state(s, state);
|
||||
} else if (state == SWAP_ACTIVATING_SIGTERM)
|
||||
swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_SUCCESS);
|
||||
else if (state == SWAP_DEACTIVATING_SIGTERM)
|
||||
} else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill)
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
|
||||
else
|
||||
swap_enter_dead(s, SWAP_SUCCESS);
|
||||
swap_enter_dead_or_active(s, SWAP_SUCCESS);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
|
||||
swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
|
||||
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static void swap_enter_activating(Swap *s) {
|
||||
@ -786,7 +786,7 @@ static void swap_enter_activating(Swap *s) {
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
|
||||
swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
|
||||
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static void swap_enter_deactivating(Swap *s) {
|
||||
@ -816,7 +816,7 @@ static void swap_enter_deactivating(Swap *s) {
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
|
||||
swap_enter_active(s, SWAP_FAILURE_RESOURCES);
|
||||
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static int swap_start(Unit *u) {
|
||||
@ -825,17 +825,14 @@ static int swap_start(Unit *u) {
|
||||
|
||||
assert(s);
|
||||
|
||||
/* We cannot fulfill this request right now, try again later
|
||||
* please! */
|
||||
|
||||
/* We cannot fulfill this request right now, try again later please! */
|
||||
if (IN_SET(s->state,
|
||||
SWAP_DEACTIVATING,
|
||||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL,
|
||||
SWAP_ACTIVATING_SIGTERM,
|
||||
SWAP_ACTIVATING_SIGKILL))
|
||||
SWAP_DEACTIVATING_SIGKILL))
|
||||
return -EAGAIN;
|
||||
|
||||
/* Already on it! */
|
||||
if (s->state == SWAP_ACTIVATING)
|
||||
return 0;
|
||||
|
||||
@ -873,21 +870,30 @@ static int swap_stop(Unit *u) {
|
||||
|
||||
assert(s);
|
||||
|
||||
if (IN_SET(s->state,
|
||||
SWAP_DEACTIVATING,
|
||||
SWAP_DEACTIVATING_SIGTERM,
|
||||
SWAP_DEACTIVATING_SIGKILL,
|
||||
SWAP_ACTIVATING_SIGTERM,
|
||||
SWAP_ACTIVATING_SIGKILL))
|
||||
switch (s->state) {
|
||||
|
||||
case SWAP_DEACTIVATING:
|
||||
case SWAP_DEACTIVATING_SIGTERM:
|
||||
case SWAP_DEACTIVATING_SIGKILL:
|
||||
/* Already on it */
|
||||
return 0;
|
||||
|
||||
assert(IN_SET(s->state, SWAP_ACTIVATING, SWAP_ACTIVATING_DONE, SWAP_ACTIVE));
|
||||
case SWAP_ACTIVATING:
|
||||
case SWAP_ACTIVATING_DONE:
|
||||
/* There's a control process pending, directly enter kill mode */
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS);
|
||||
return 0;
|
||||
|
||||
if (detect_container() > 0)
|
||||
return -EPERM;
|
||||
case SWAP_ACTIVE:
|
||||
if (detect_container() > 0)
|
||||
return -EPERM;
|
||||
|
||||
swap_enter_deactivating(s);
|
||||
return 1;
|
||||
swap_enter_deactivating(s);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unexpected state.");
|
||||
}
|
||||
}
|
||||
|
||||
static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
@ -1015,10 +1021,8 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
case SWAP_ACTIVATING:
|
||||
case SWAP_ACTIVATING_DONE:
|
||||
case SWAP_ACTIVATING_SIGTERM:
|
||||
case SWAP_ACTIVATING_SIGKILL:
|
||||
|
||||
if (f == SWAP_SUCCESS)
|
||||
if (f == SWAP_SUCCESS || s->from_proc_swaps)
|
||||
swap_enter_active(s, f);
|
||||
else
|
||||
swap_enter_dead(s, f);
|
||||
@ -1028,7 +1032,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
case SWAP_DEACTIVATING_SIGKILL:
|
||||
case SWAP_DEACTIVATING_SIGTERM:
|
||||
|
||||
swap_enter_dead(s, f);
|
||||
swap_enter_dead_or_active(s, f);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1050,7 +1054,7 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
|
||||
case SWAP_ACTIVATING:
|
||||
case SWAP_ACTIVATING_DONE:
|
||||
log_unit_warning(UNIT(s), "Activation timed out. Stopping.");
|
||||
swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SWAP_DEACTIVATING:
|
||||
@ -1058,30 +1062,19 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SWAP_ACTIVATING_SIGTERM:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "Activation timed out. Killing.");
|
||||
swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "Activation timed out. Skipping SIGKILL. Ignoring.");
|
||||
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SWAP_DEACTIVATING_SIGTERM:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "Deactivation timed out. Killing.");
|
||||
log_unit_warning(UNIT(s), "Swap process timed out. Killing.");
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "Deactivation timed out. Skipping SIGKILL. Ignoring.");
|
||||
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
|
||||
log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring.");
|
||||
swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SWAP_ACTIVATING_SIGKILL:
|
||||
case SWAP_DEACTIVATING_SIGKILL:
|
||||
log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring.");
|
||||
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
|
||||
swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -55,9 +55,54 @@ static void test_set_put(void) {
|
||||
assert_se(set_put(m, (void*) "22") == 0);
|
||||
}
|
||||
|
||||
static void test_set_make(void) {
|
||||
_cleanup_set_free_ Set *s = NULL;
|
||||
|
||||
assert_se(set_make(&s, NULL, UINT_TO_PTR(4), UINT_TO_PTR(6), UINT_TO_PTR(8), NULL) == 0);
|
||||
assert_se(set_size(s) == 3);
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(0)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(1)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(2)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(3)));
|
||||
assert_se(set_contains(s, UINT_TO_PTR(4)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(5)));
|
||||
assert_se(set_contains(s, UINT_TO_PTR(6)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(7)));
|
||||
assert_se(set_contains(s, UINT_TO_PTR(8)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(9)));
|
||||
s = set_free(s);
|
||||
|
||||
assert_se(set_make(&s, NULL, NULL) == 0);
|
||||
assert_se(set_size(s) == 0);
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(0)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(4)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(6)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(8)));
|
||||
s = set_free(s);
|
||||
|
||||
assert_se(set_make(&s, NULL, UINT_TO_PTR(3), NULL) == 0);
|
||||
assert_se(set_size(s) == 1);
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(0)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(1)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(2)));
|
||||
assert_se(set_contains(s, UINT_TO_PTR(3)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(4)));
|
||||
|
||||
assert_se(set_make(&s, NULL, UINT_TO_PTR(2), UINT_TO_PTR(5), NULL) == 0);
|
||||
assert_se(set_size(s) == 2);
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(0)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(1)));
|
||||
assert_se(set_contains(s, UINT_TO_PTR(2)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(3)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(4)));
|
||||
assert_se(set_contains(s, UINT_TO_PTR(5)));
|
||||
assert_se(!set_contains(s, UINT_TO_PTR(6)));
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
test_set_steal_first();
|
||||
test_set_put();
|
||||
test_set_make();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user