Merge pull request #13439 from yuwata/core-support-systemctl-clean-more

core: support systemctl clean more
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2019-09-13 16:15:02 +02:00
committed by GitHub
12 changed files with 448 additions and 39 deletions
+6 -3
View File
@@ -136,7 +136,8 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
[MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
[MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
[MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
[MOUNT_FAILED] = "failed"
[MOUNT_FAILED] = "failed",
[MOUNT_CLEANING] = "cleaning",
};
DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
@@ -204,7 +205,8 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
[SOCKET_STOP_POST] = "stop-post",
[SOCKET_FINAL_SIGTERM] = "final-sigterm",
[SOCKET_FINAL_SIGKILL] = "final-sigkill",
[SOCKET_FAILED] = "failed"
[SOCKET_FAILED] = "failed",
[SOCKET_CLEANING] = "cleaning",
};
DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
@@ -217,7 +219,8 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
[SWAP_DEACTIVATING] = "deactivating",
[SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
[SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
[SWAP_FAILED] = "failed"
[SWAP_FAILED] = "failed",
[SWAP_CLEANING] = "cleaning",
};
DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
+3
View File
@@ -79,6 +79,7 @@ typedef enum MountState {
MOUNT_UNMOUNTING_SIGTERM,
MOUNT_UNMOUNTING_SIGKILL,
MOUNT_FAILED,
MOUNT_CLEANING,
_MOUNT_STATE_MAX,
_MOUNT_STATE_INVALID = -1
} MountState;
@@ -147,6 +148,7 @@ typedef enum SocketState {
SOCKET_FINAL_SIGTERM,
SOCKET_FINAL_SIGKILL,
SOCKET_FAILED,
SOCKET_CLEANING,
_SOCKET_STATE_MAX,
_SOCKET_STATE_INVALID = -1
} SocketState;
@@ -160,6 +162,7 @@ typedef enum SwapState {
SWAP_DEACTIVATING_SIGTERM,
SWAP_DEACTIVATING_SIGKILL,
SWAP_FAILED,
SWAP_CLEANING,
_SWAP_STATE_MAX,
_SWAP_STATE_INVALID = -1
} SwapState;
+82 -3
View File
@@ -45,7 +45,8 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
[MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
[MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
[MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
[MOUNT_FAILED] = UNIT_FAILED
[MOUNT_FAILED] = UNIT_FAILED,
[MOUNT_CLEANING] = UNIT_MAINTENANCE,
};
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
@@ -61,7 +62,8 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
MOUNT_REMOUNTING_SIGKILL,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
MOUNT_UNMOUNTING_SIGKILL);
MOUNT_UNMOUNTING_SIGKILL,
MOUNT_CLEANING);
}
static bool mount_is_network(const MountParameters *p) {
@@ -731,6 +733,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sMount State: %s\n"
"%sResult: %s\n"
"%sClean Result: %s\n"
"%sWhere: %s\n"
"%sWhat: %s\n"
"%sFile System Type: %s\n"
@@ -745,6 +748,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
"%sTimeoutSec: %s\n",
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
prefix, mount_result_to_string(m->clean_result),
prefix, m->where,
prefix, p ? strna(p->what) : "n/a",
prefix, p ? strna(p->fstype) : "n/a",
@@ -1090,7 +1094,8 @@ static int mount_start(Unit *u) {
if (IN_SET(m->state,
MOUNT_UNMOUNTING,
MOUNT_UNMOUNTING_SIGTERM,
MOUNT_UNMOUNTING_SIGKILL))
MOUNT_UNMOUNTING_SIGKILL,
MOUNT_CLEANING))
return -EAGAIN;
/* Already on it! */
@@ -1149,6 +1154,11 @@ static int mount_stop(Unit *u) {
mount_enter_unmounting(m);
return 1;
case MOUNT_CLEANING:
/* If we are currently cleaning, then abort it, brutally. */
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
return 0;
default:
assert_not_reached("Unexpected state.");
}
@@ -1382,6 +1392,13 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
mount_enter_dead_or_mounted(m, f);
break;
case MOUNT_CLEANING:
if (m->clean_result == MOUNT_SUCCESS)
m->clean_result = f;
mount_enter_dead(m, MOUNT_SUCCESS);
break;
default:
assert_not_reached("Uh, control process died at wrong time.");
}
@@ -1449,6 +1466,15 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
break;
case MOUNT_CLEANING:
log_unit_warning(UNIT(m), "Cleaning timed out. killing.");
if (m->clean_result == MOUNT_SUCCESS)
m->clean_result = MOUNT_FAILURE_TIMEOUT;
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, 0);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
@@ -1923,6 +1949,7 @@ static void mount_reset_failed(Unit *u) {
m->result = MOUNT_SUCCESS;
m->reload_result = MOUNT_SUCCESS;
m->clean_result = MOUNT_SUCCESS;
}
static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
@@ -1941,6 +1968,56 @@ static int mount_control_pid(Unit *u) {
return m->control_pid;
}
static int mount_clean(Unit *u, ExecCleanMask mask) {
_cleanup_strv_free_ char **l = NULL;
Mount *m = MOUNT(u);
int r;
assert(m);
assert(mask != 0);
if (m->state != MOUNT_DEAD)
return -EBUSY;
r = exec_context_get_clean_directories(&m->exec_context, u->manager->prefix, mask, &l);
if (r < 0)
return r;
if (strv_isempty(l))
return -EUNATCH;
mount_unwatch_control_pid(m);
m->clean_result = MOUNT_SUCCESS;
m->control_command = NULL;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->exec_context.timeout_clean_usec));
if (r < 0)
goto fail;
r = unit_fork_and_watch_rm_rf(u, l, &m->control_pid);
if (r < 0)
goto fail;
mount_set_state(m, MOUNT_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
m->clean_result = MOUNT_FAILURE_RESOURCES;
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
return r;
}
static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
Mount *m = MOUNT(u);
assert(m);
return exec_context_get_clean_mask(&m->exec_context, ret);
}
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
[MOUNT_EXEC_MOUNT] = "ExecMount",
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
@@ -1989,6 +2066,8 @@ const UnitVTable mount_vtable = {
.reload = mount_reload,
.kill = mount_kill,
.clean = mount_clean,
.can_clean = mount_can_clean,
.serialize = mount_serialize,
.deserialize_item = mount_deserialize_item,
+1
View File
@@ -61,6 +61,7 @@ struct Mount {
MountResult result;
MountResult reload_result;
MountResult clean_result;
mode_t directory_mode;
+2 -24
View File
@@ -30,7 +30,6 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rm-rf.h"
#include "serialize.h"
#include "service.h"
#include "signal-util.h"
@@ -4246,7 +4245,6 @@ static int service_exit_status(Unit *u) {
static int service_clean(Unit *u, ExecCleanMask mask) {
_cleanup_strv_free_ char **l = NULL;
Service *s = SERVICE(u);
pid_t pid;
int r;
assert(s);
@@ -4271,36 +4269,16 @@ static int service_clean(Unit *u, ExecCleanMask mask) {
if (r < 0)
goto fail;
r = unit_fork_helper_process(UNIT(s), "(sd-rmrf)", &pid);
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
goto fail;
if (r == 0) {
int ret = EXIT_SUCCESS;
char **i;
STRV_FOREACH(i, l) {
r = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_MISSING_OK);
if (r < 0) {
log_error_errno(r, "Failed to remove '%s': %m", *i);
ret = EXIT_FAILURE;
}
}
_exit(ret);
}
r = unit_watch_pid(u, pid, true);
if (r < 0)
goto fail;
s->control_pid = pid;
service_set_state(s, SERVICE_CLEANING);
return 0;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to initiate cleaning: %m");
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
s->clean_result = SERVICE_FAILURE_RESOURCES;
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return r;
+89 -6
View File
@@ -67,7 +67,8 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
[SOCKET_STOP_POST] = UNIT_DEACTIVATING,
[SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
[SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
[SOCKET_FAILED] = UNIT_FAILED
[SOCKET_FAILED] = UNIT_FAILED,
[SOCKET_CLEANING] = UNIT_MAINTENANCE,
};
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
@@ -624,6 +625,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sSocket State: %s\n"
"%sResult: %s\n"
"%sClean Result: %s\n"
"%sBindIPv6Only: %s\n"
"%sBacklog: %u\n"
"%sSocketMode: %04o\n"
@@ -642,6 +644,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sSELinuxContextFromNet: %s\n",
prefix, socket_state_to_string(s->state),
prefix, socket_result_to_string(s->result),
prefix, socket_result_to_string(s->clean_result),
prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
prefix, s->backlog,
prefix, s->socket_mode,
@@ -1802,7 +1805,8 @@ static void socket_set_state(Socket *s, SocketState state) {
SOCKET_STOP_PRE_SIGKILL,
SOCKET_STOP_POST,
SOCKET_FINAL_SIGTERM,
SOCKET_FINAL_SIGKILL)) {
SOCKET_FINAL_SIGKILL,
SOCKET_CLEANING)) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
socket_unwatch_control_pid(s);
@@ -1820,7 +1824,8 @@ static void socket_set_state(Socket *s, SocketState state) {
SOCKET_RUNNING,
SOCKET_STOP_PRE,
SOCKET_STOP_PRE_SIGTERM,
SOCKET_STOP_PRE_SIGKILL))
SOCKET_STOP_PRE_SIGKILL,
SOCKET_CLEANING))
socket_close_fds(s);
if (state != old_state)
@@ -1850,7 +1855,8 @@ static int socket_coldplug(Unit *u) {
SOCKET_STOP_PRE_SIGKILL,
SOCKET_STOP_POST,
SOCKET_FINAL_SIGTERM,
SOCKET_FINAL_SIGKILL)) {
SOCKET_FINAL_SIGKILL,
SOCKET_CLEANING)) {
r = unit_watch_pid(UNIT(s), s->control_pid, false);
if (r < 0)
@@ -1891,7 +1897,7 @@ static int socket_coldplug(Unit *u) {
return r;
}
if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED)) {
if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED, SOCKET_CLEANING)) {
(void) unit_setup_dynamic_creds(u);
(void) unit_setup_exec_runtime(u);
}
@@ -2455,7 +2461,8 @@ static int socket_start(Unit *u) {
SOCKET_STOP_PRE_SIGTERM,
SOCKET_STOP_POST,
SOCKET_FINAL_SIGTERM,
SOCKET_FINAL_SIGKILL))
SOCKET_FINAL_SIGKILL,
SOCKET_CLEANING))
return -EAGAIN;
/* Already on it! */
@@ -2530,6 +2537,12 @@ static int socket_stop(Unit *u) {
return -EAGAIN;
}
/* If we are currently cleaning, then abort it, brutally. */
if (s->state == SOCKET_CLEANING) {
socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_SUCCESS);
return 0;
}
assert(IN_SET(s->state, SOCKET_LISTENING, SOCKET_RUNNING));
socket_enter_stop_pre(s, SOCKET_SUCCESS);
@@ -3073,6 +3086,14 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
socket_enter_dead(s, f);
break;
case SOCKET_CLEANING:
if (s->clean_result == SOCKET_SUCCESS)
s->clean_result = f;
socket_enter_dead(s, SOCKET_SUCCESS);
break;
default:
assert_not_reached("Uh, control process died at wrong time.");
}
@@ -3141,6 +3162,15 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use
socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
break;
case SOCKET_CLEANING:
log_unit_warning(UNIT(s), "Cleaning timed out. killing.");
if (s->clean_result == SOCKET_SUCCESS)
s->clean_result = SOCKET_FAILURE_TIMEOUT;
socket_enter_signal(s, SOCKET_FINAL_SIGKILL, 0);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
@@ -3197,6 +3227,7 @@ static void socket_reset_failed(Unit *u) {
socket_set_state(s, SOCKET_DEAD);
s->result = SOCKET_SUCCESS;
s->clean_result = SOCKET_SUCCESS;
}
void socket_connection_unref(Socket *s) {
@@ -3291,6 +3322,56 @@ static int socket_control_pid(Unit *u) {
return s->control_pid;
}
static int socket_clean(Unit *u, ExecCleanMask mask) {
_cleanup_strv_free_ char **l = NULL;
Socket *s = SOCKET(u);
int r;
assert(s);
assert(mask != 0);
if (s->state != SOCKET_DEAD)
return -EBUSY;
r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
if (r < 0)
return r;
if (strv_isempty(l))
return -EUNATCH;
socket_unwatch_control_pid(s);
s->clean_result = SOCKET_SUCCESS;
s->control_command = NULL;
s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
if (r < 0)
goto fail;
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
goto fail;
socket_set_state(s, SOCKET_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
s->clean_result = SOCKET_FAILURE_RESOURCES;
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return r;
}
static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
Socket *s = SOCKET(u);
assert(s);
return exec_context_get_clean_mask(&s->exec_context, ret);
}
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
[SOCKET_EXEC_START_PRE] = "ExecStartPre",
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
@@ -3343,6 +3424,8 @@ const UnitVTable socket_vtable = {
.stop = socket_stop,
.kill = socket_kill,
.clean = socket_clean,
.can_clean = socket_can_clean,
.get_timeout = socket_get_timeout,
+1
View File
@@ -103,6 +103,7 @@ struct Socket {
mode_t socket_mode;
SocketResult result;
SocketResult clean_result;
char **symlinks;
+83 -3
View File
@@ -38,7 +38,8 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
[SWAP_DEACTIVATING] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING,
[SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING,
[SWAP_FAILED] = UNIT_FAILED
[SWAP_FAILED] = UNIT_FAILED,
[SWAP_CLEANING] = UNIT_MAINTENANCE,
};
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
@@ -51,7 +52,8 @@ static bool SWAP_STATE_WITH_PROCESS(SwapState state) {
SWAP_ACTIVATING_DONE,
SWAP_DEACTIVATING,
SWAP_DEACTIVATING_SIGTERM,
SWAP_DEACTIVATING_SIGKILL);
SWAP_DEACTIVATING_SIGKILL,
SWAP_CLEANING);
}
static void swap_unset_proc_swaps(Swap *s) {
@@ -587,11 +589,13 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sSwap State: %s\n"
"%sResult: %s\n"
"%sClean Result: %s\n"
"%sWhat: %s\n"
"%sFrom /proc/swaps: %s\n"
"%sFrom fragment: %s\n",
prefix, swap_state_to_string(s->state),
prefix, swap_result_to_string(s->result),
prefix, swap_result_to_string(s->clean_result),
prefix, s->what,
prefix, yes_no(s->from_proc_swaps),
prefix, yes_no(s->from_fragment));
@@ -852,7 +856,8 @@ static int swap_start(Unit *u) {
if (IN_SET(s->state,
SWAP_DEACTIVATING,
SWAP_DEACTIVATING_SIGTERM,
SWAP_DEACTIVATING_SIGKILL))
SWAP_DEACTIVATING_SIGKILL,
SWAP_CLEANING))
return -EAGAIN;
/* Already on it! */
@@ -912,6 +917,12 @@ static int swap_stop(Unit *u) {
swap_enter_deactivating(s);
return 1;
case SWAP_CLEANING:
/* If we are currently cleaning, then abort it, brutally. */
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS);
return 0;
default:
assert_not_reached("Unexpected state.");
}
@@ -1067,6 +1078,13 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
swap_enter_dead_or_active(s, f);
break;
case SWAP_CLEANING:
if (s->clean_result == SWAP_SUCCESS)
s->clean_result = f;
swap_enter_dead(s, SWAP_SUCCESS);
break;
default:
assert_not_reached("Uh, control process died at wrong time.");
}
@@ -1109,6 +1127,15 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT);
break;
case SWAP_CLEANING:
log_unit_warning(UNIT(s), "Cleaning timed out. killing.");
if (s->clean_result == SWAP_SUCCESS)
s->clean_result = SWAP_FAILURE_TIMEOUT;
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, 0);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
@@ -1428,6 +1455,7 @@ static void swap_reset_failed(Unit *u) {
swap_set_state(s, SWAP_DEAD);
s->result = SWAP_SUCCESS;
s->clean_result = SWAP_SUCCESS;
}
static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
@@ -1475,6 +1503,56 @@ static int swap_control_pid(Unit *u) {
return s->control_pid;
}
static int swap_clean(Unit *u, ExecCleanMask mask) {
_cleanup_strv_free_ char **l = NULL;
Swap *s = SWAP(u);
int r;
assert(s);
assert(mask != 0);
if (s->state != SWAP_DEAD)
return -EBUSY;
r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
if (r < 0)
return r;
if (strv_isempty(l))
return -EUNATCH;
swap_unwatch_control_pid(s);
s->clean_result = SWAP_SUCCESS;
s->control_command = NULL;
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
if (r < 0)
goto fail;
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
goto fail;
swap_set_state(s, SWAP_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
s->clean_result = SWAP_FAILURE_RESOURCES;
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return r;
}
static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
Swap *s = SWAP(u);
assert(s);
return exec_context_get_clean_mask(&s->exec_context, ret);
}
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
[SWAP_EXEC_ACTIVATE] = "ExecActivate",
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
@@ -1520,6 +1598,8 @@ const UnitVTable swap_vtable = {
.stop = swap_stop,
.kill = swap_kill,
.clean = swap_clean,
.can_clean = swap_can_clean,
.get_timeout = swap_get_timeout,
+1
View File
@@ -57,6 +57,7 @@ struct Swap {
bool just_activated:1;
SwapResult result;
SwapResult clean_result;
usec_t timeout_usec;
+34
View File
@@ -38,6 +38,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rm-rf.h"
#include "serialize.h"
#include "set.h"
#include "signal-util.h"
@@ -5296,6 +5297,39 @@ int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret) {
return 0;
}
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid) {
pid_t pid;
int r;
assert(u);
assert(ret_pid);
r = unit_fork_helper_process(u, "(sd-rmrf)", &pid);
if (r < 0)
return r;
if (r == 0) {
int ret = EXIT_SUCCESS;
char **i;
STRV_FOREACH(i, paths) {
r = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_MISSING_OK);
if (r < 0) {
log_error_errno(r, "Failed to remove '%s': %m", *i);
ret = EXIT_FAILURE;
}
}
_exit(ret);
}
r = unit_watch_pid(u, pid, true);
if (r < 0)
return r;
*ret_pid = pid;
return 0;
}
static void unit_update_dependency_mask(Unit *u, UnitDependency d, Unit *other, UnitDependencyInfo di) {
assert(u);
assert(d >= 0);
+1
View File
@@ -825,6 +825,7 @@ bool unit_shall_confirm_spawn(Unit *u);
int unit_set_exec_params(Unit *s, ExecParameters *p);
int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret);
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid);
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask);
+145
View File
@@ -169,6 +169,151 @@ systemctl clean testservice --what=all
! test -L /var/cache/testservice
! test -L /var/log/testservice
cat > /etc/systemd/system/tmp-hoge.mount <<EOF
[Mount]
What=tmpfs
Type=tmpfs
ConfigurationDirectory=hoge
RuntimeDirectory=hoge
StateDirectory=hoge
CacheDirectory=hoge
LogsDirectory=hoge
EOF
systemctl daemon-reload
! test -e /etc/hoge
! test -e /run/hoge
! test -e /var/lib/hoge
! test -e /var/cache/hoge
! test -e /var/log/hoge
systemctl start tmp-hoge.mount
test -d /etc/hoge
test -d /run/hoge
test -d /var/lib/hoge
test -d /var/cache/hoge
test -d /var/log/hoge
! systemctl clean tmp-hoge.mount
test -d /etc/hoge
test -d /run/hoge
test -d /var/lib/hoge
test -d /var/cache/hoge
test -d /var/log/hoge
systemctl stop tmp-hoge.mount
test -d /etc/hoge
! test -d /run/hoge
test -d /var/lib/hoge
test -d /var/cache/hoge
test -d /var/log/hoge
systemctl clean tmp-hoge.mount --what=configuration
! test -d /etc/hoge
! test -d /run/hoge
test -d /var/lib/hoge
test -d /var/cache/hoge
test -d /var/log/hoge
systemctl clean tmp-hoge.mount
! test -d /etc/hoge
! test -d /run/hoge
test -d /var/lib/hoge
! test -d /var/cache/hoge
test -d /var/log/hoge
systemctl clean tmp-hoge.mount --what=logs
! test -d /etc/hoge
! test -d /run/hoge
test -d /var/lib/hoge
! test -d /var/cache/hoge
! test -d /var/log/hoge
systemctl clean tmp-hoge.mount --what=all
! test -d /etc/hoge
! test -d /run/hoge
! test -d /var/lib/hoge
! test -d /var/cache/hoge
! test -d /var/log/hoge
cat > /etc/systemd/system/testservice.socket <<EOF
[Socket]
ListenSequentialPacket=/run/testservice.socket
RemoveOnStop=yes
ExecStartPre=true
ConfigurationDirectory=testsocket
RuntimeDirectory=testsocket
StateDirectory=testsocket
CacheDirectory=testsocket
LogsDirectory=testsocket
EOF
systemctl daemon-reload
! test -e /etc/testsocket
! test -e /run/testsocket
! test -e /var/lib/testsocket
! test -e /var/cache/testsocket
! test -e /var/log/testsocket
systemctl start testservice.socket
test -d /etc/testsocket
! test -d /run/testsocket
test -d /var/lib/testsocket
test -d /var/cache/testsocket
test -d /var/log/testsocket
! systemctl clean testservice.socket
systemctl stop testservice.socket
test -d /etc/testsocket
! test -d /run/testsocket
test -d /var/lib/testsocket
test -d /var/cache/testsocket
test -d /var/log/testsocket
systemctl clean testservice.socket --what=configuration
! test -e /etc/testsocket
! test -d /run/testsocket
test -d /var/lib/testsocket
test -d /var/cache/testsocket
test -d /var/log/testsocket
systemctl clean testservice.socket
! test -e /etc/testsocket
! test -e /run/testsocket
test -d /var/lib/testsocket
! test -e /var/cache/testsocket
test -d /var/log/testsocket
systemctl clean testservice.socket --what=logs
! test -e /etc/testsocket
! test -e /run/testsocket
test -d /var/lib/testsocket
! test -e /var/cache/testsocket
! test -e /var/log/testsocket
systemctl clean testservice.socket --what=all
! test -e /etc/testsocket
! test -e /run/testsocket
! test -e /var/lib/testsocket
! test -e /var/cache/testsocket
! test -e /var/log/testsocket
echo OK > /testok
exit 0