1
0
mirror of https://github.com/systemd/systemd synced 2026-03-18 11:04:46 +01:00

Compare commits

..

No commits in common. "7ad9bad71b077f6a4629f4e48fb9ad26e1784809" and "60809871305ebef6b1f44552524d5cf7c7e9bc6d" have entirely different histories.

10 changed files with 85 additions and 128 deletions

View File

@ -6371,24 +6371,38 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
return 0;
}
if (hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops) < 0)
return log_oom();
r = hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops);
if (r < 0) {
log_unit_debug_errno(u, r, "Failed to allocate storage for runtime parameter: %m");
return 0;
}
rt = hashmap_get(u->manager->exec_runtime_by_id, u->id);
if (!rt) {
if (exec_runtime_allocate(&rt_create, u->id) < 0)
r = exec_runtime_allocate(&rt_create, u->id);
if (r < 0)
return log_oom();
rt = rt_create;
}
if (streq(key, "tmp-dir")) {
if (free_and_strdup_warn(&rt->tmp_dir, value) < 0)
return -ENOMEM;
char *copy;
copy = strdup(value);
if (!copy)
return log_oom();
free_and_replace(rt->tmp_dir, copy);
} else if (streq(key, "var-tmp-dir")) {
if (free_and_strdup_warn(&rt->var_tmp_dir, value) < 0)
return -ENOMEM;
char *copy;
copy = strdup(value);
if (!copy)
return log_oom();
free_and_replace(rt->var_tmp_dir, copy);
} else if (streq(key, "netns-socket-0")) {
int fd;
@ -6412,6 +6426,27 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
safe_close(rt->netns_storage_socket[1]);
rt->netns_storage_socket[1] = fdset_remove(fds, fd);
} else if (streq(key, "ipcns-socket-0")) {
int fd;
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
log_unit_debug(u, "Failed to parse ipcns socket value: %s", value);
return 0;
}
safe_close(rt->ipcns_storage_socket[0]);
rt->ipcns_storage_socket[0] = fdset_remove(fds, fd);
} else if (streq(key, "ipcns-socket-1")) {
int fd;
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
log_unit_debug(u, "Failed to parse ipcns socket value: %s", value);
return 0;
}
safe_close(rt->ipcns_storage_socket[1]);
rt->ipcns_storage_socket[1] = fdset_remove(fds, fd);
} else
return 0;

View File

@ -108,9 +108,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool switching_root) {
fputs(u->id, f);
fputc('\n', f);
assert(!!UNIT_VTABLE(u)->serialize == !!UNIT_VTABLE(u)->deserialize_item);
if (UNIT_VTABLE(u)->serialize) {
if (unit_can_serialize(u)) {
r = UNIT_VTABLE(u)->serialize(u, f, fds);
if (r < 0)
return r;
@ -500,15 +498,17 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
continue;
}
r = exec_runtime_deserialize_compat(u, l, v, fds);
if (r < 0) {
log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
continue;
} else if (r > 0)
/* Returns positive if key was handled by the call */
continue;
if (unit_can_serialize(u)) {
r = exec_runtime_deserialize_compat(u, l, v, fds);
if (r < 0) {
log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
continue;
}
/* Returns positive if key was handled by the call */
if (r > 0)
continue;
if (UNIT_VTABLE(u)->deserialize_item) {
r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
if (r < 0)
log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);

View File

@ -3488,6 +3488,12 @@ void unit_unwatch_bus_name(Unit *u, const char *name) {
u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
}
bool unit_can_serialize(Unit *u) {
assert(u);
return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
}
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
_cleanup_free_ char *e = NULL;
Unit *device;

View File

@ -814,6 +814,8 @@ char *unit_dbus_path_invocation_id(Unit *u);
int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
bool unit_can_serialize(Unit *u) _pure_;
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);

View File

@ -237,6 +237,25 @@ static usec_t time_event_source_next(const sd_event_source *s) {
return USEC_INFINITY;
}
static int earliest_time_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
/* Enabled ones first */
if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
return -1;
if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
return 1;
/* Move the pending ones to the end */
if (!x->pending && y->pending)
return -1;
if (x->pending && !y->pending)
return 1;
/* Order by time */
return CMP(time_event_source_next(x), time_event_source_next(y));
}
static usec_t time_event_source_latest(const sd_event_source *s) {
assert(s);
@ -255,15 +274,7 @@ static usec_t time_event_source_latest(const sd_event_source *s) {
return USEC_INFINITY;
}
static bool event_source_timer_candidate(const sd_event_source *s) {
assert(s);
/* Returns true for event sources that either are not pending yet (i.e. where it's worth to mark them pending)
* or which are currently ratelimited (i.e. where it's worth leaving the ratelimited state) */
return !s->pending || s->ratelimited;
}
static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(const sd_event_source *s)) {
static int latest_time_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
/* Enabled ones first */
@ -272,22 +283,14 @@ static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(
if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
return 1;
/* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */
if (event_source_timer_candidate(x) && !event_source_timer_candidate(y))
/* Move the pending ones to the end */
if (!x->pending && y->pending)
return -1;
if (!event_source_timer_candidate(x) && event_source_timer_candidate(y))
if (x->pending && !y->pending)
return 1;
/* Order by time */
return CMP(time_func(x), time_func(y));
}
static int earliest_time_prioq_compare(const void *a, const void *b) {
return time_prioq_compare(a, b, time_event_source_next);
}
static int latest_time_prioq_compare(const void *a, const void *b) {
return time_prioq_compare(a, b, time_event_source_latest);
return CMP(time_event_source_latest(x), time_event_source_latest(y));
}
static int exit_prioq_compare(const void *a, const void *b) {

View File

@ -67,5 +67,3 @@ lt.l4 lt pc105 - terminate:ctrl_alt_bksp
lt lt pc105 - terminate:ctrl_alt_bksp
khmer kh,us pc105 - terminate:ctrl_alt_bksp
es-dvorak es microsoftpro dvorak terminate:ctrl_alt_bksp
lv lv pc105 apostrophe terminate:ctrl_alt_bksp
lv-tilde lv pc105 tilde terminate:ctrl_alt_bksp

View File

@ -1 +0,0 @@
../TEST-01-BASIC/Makefile

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -e
TEST_DESCRIPTION="Test that mount/unmount storms can enter/exit rate limit state and will not leak units"
. $TEST_BASE_DIR/test-functions
do_test "$@"

View File

@ -1,6 +0,0 @@
[Unit]
Description=TEST-60-MOUNT-RATELIMIT
[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh

View File

@ -1,73 +0,0 @@
#!/usr/bin/env bash
set -eux
set -o pipefail
systemd-analyze log-level debug
systemd-analyze log-target journal
NUM_DIRS=20
# mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting
for ((i = 0; i < NUM_DIRS; i++)); do
mkdir "/tmp/meow${i}"
done
for ((i = 0; i < NUM_DIRS; i++)); do
mount -t tmpfs tmpfs "/tmp/meow${i}"
done
systemctl daemon-reload
systemctl list-units -t mount tmp-meow* | grep -q tmp-meow
for ((i = 0; i < NUM_DIRS; i++)); do
umount "/tmp/meow${i}"
done
# figure out if we have entered the rate limit state
exited_rl=0
timeout="$(date -ud "2 minutes" +%s)"
while [[ $(date -u +%s) -le ${timeout} ]]; do
if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) entered rate limit"; then
entered_rl=1
break
fi
sleep 5
done
# if the infra is slow we might not enter the rate limit state; in that case skip the exit check
if [ "${entered_rl}" = "1" ]; then
exited_rl=0
timeout="$(date -ud "2 minutes" +%s)"
while [[ $(date -u +%s) -le ${timeout} ]]; do
if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) left rate limit"; then
exited_rl=1
break
fi
sleep 5
done
if [ "${exited_rl}" = "0" ]; then
exit 24
fi
fi
# give some time for units to settle so we don't race between exiting the rate limit state and cleaning up the units
sleep 60
systemctl daemon-reload
sleep 60
# verify that the mount units are always cleaned up at the end
if systemctl list-units -t mount tmp-meow* | grep -q tmp-meow; then
exit 42
fi
systemd-analyze log-level info
echo OK >/testok
exit 0