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.
7ad9bad71b
...
6080987130
@ -6371,24 +6371,38 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops) < 0)
|
r = hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops);
|
||||||
return log_oom();
|
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);
|
rt = hashmap_get(u->manager->exec_runtime_by_id, u->id);
|
||||||
if (!rt) {
|
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();
|
return log_oom();
|
||||||
|
|
||||||
rt = rt_create;
|
rt = rt_create;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streq(key, "tmp-dir")) {
|
if (streq(key, "tmp-dir")) {
|
||||||
if (free_and_strdup_warn(&rt->tmp_dir, value) < 0)
|
char *copy;
|
||||||
return -ENOMEM;
|
|
||||||
|
copy = strdup(value);
|
||||||
|
if (!copy)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
free_and_replace(rt->tmp_dir, copy);
|
||||||
|
|
||||||
} else if (streq(key, "var-tmp-dir")) {
|
} else if (streq(key, "var-tmp-dir")) {
|
||||||
if (free_and_strdup_warn(&rt->var_tmp_dir, value) < 0)
|
char *copy;
|
||||||
return -ENOMEM;
|
|
||||||
|
copy = strdup(value);
|
||||||
|
if (!copy)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
free_and_replace(rt->var_tmp_dir, copy);
|
||||||
|
|
||||||
} else if (streq(key, "netns-socket-0")) {
|
} else if (streq(key, "netns-socket-0")) {
|
||||||
int fd;
|
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]);
|
safe_close(rt->netns_storage_socket[1]);
|
||||||
rt->netns_storage_socket[1] = fdset_remove(fds, fd);
|
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
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@ -108,9 +108,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool switching_root) {
|
|||||||
fputs(u->id, f);
|
fputs(u->id, f);
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
|
|
||||||
assert(!!UNIT_VTABLE(u)->serialize == !!UNIT_VTABLE(u)->deserialize_item);
|
if (unit_can_serialize(u)) {
|
||||||
|
|
||||||
if (UNIT_VTABLE(u)->serialize) {
|
|
||||||
r = UNIT_VTABLE(u)->serialize(u, f, fds);
|
r = UNIT_VTABLE(u)->serialize(u, f, fds);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -500,15 +498,17 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unit_can_serialize(u)) {
|
||||||
r = exec_runtime_deserialize_compat(u, l, v, fds);
|
r = exec_runtime_deserialize_compat(u, l, v, fds);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
|
log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l);
|
||||||
continue;
|
continue;
|
||||||
} else if (r > 0)
|
}
|
||||||
|
|
||||||
/* Returns positive if key was handled by the call */
|
/* Returns positive if key was handled by the call */
|
||||||
|
if (r > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (UNIT_VTABLE(u)->deserialize_item) {
|
|
||||||
r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
|
r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
|
log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l);
|
||||||
|
|||||||
@ -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);
|
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) {
|
int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
|
||||||
_cleanup_free_ char *e = NULL;
|
_cleanup_free_ char *e = NULL;
|
||||||
Unit *device;
|
Unit *device;
|
||||||
|
|||||||
@ -814,6 +814,8 @@ char *unit_dbus_path_invocation_id(Unit *u);
|
|||||||
|
|
||||||
int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
|
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_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
|
||||||
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
|
int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
|
||||||
|
|
||||||
|
|||||||
@ -237,6 +237,25 @@ static usec_t time_event_source_next(const sd_event_source *s) {
|
|||||||
return USEC_INFINITY;
|
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) {
|
static usec_t time_event_source_latest(const sd_event_source *s) {
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
@ -255,15 +274,7 @@ static usec_t time_event_source_latest(const sd_event_source *s) {
|
|||||||
return USEC_INFINITY;
|
return USEC_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool event_source_timer_candidate(const sd_event_source *s) {
|
static int latest_time_prioq_compare(const void *a, const void *b) {
|
||||||
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)) {
|
|
||||||
const sd_event_source *x = a, *y = b;
|
const sd_event_source *x = a, *y = b;
|
||||||
|
|
||||||
/* Enabled ones first */
|
/* 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)
|
if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */
|
/* Move the pending ones to the end */
|
||||||
if (event_source_timer_candidate(x) && !event_source_timer_candidate(y))
|
if (!x->pending && y->pending)
|
||||||
return -1;
|
return -1;
|
||||||
if (!event_source_timer_candidate(x) && event_source_timer_candidate(y))
|
if (x->pending && !y->pending)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Order by time */
|
/* Order by time */
|
||||||
return CMP(time_func(x), time_func(y));
|
return CMP(time_event_source_latest(x), time_event_source_latest(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exit_prioq_compare(const void *a, const void *b) {
|
static int exit_prioq_compare(const void *a, const void *b) {
|
||||||
|
|||||||
@ -67,5 +67,3 @@ lt.l4 lt pc105 - terminate:ctrl_alt_bksp
|
|||||||
lt lt pc105 - terminate:ctrl_alt_bksp
|
lt lt pc105 - terminate:ctrl_alt_bksp
|
||||||
khmer kh,us pc105 - terminate:ctrl_alt_bksp
|
khmer kh,us pc105 - terminate:ctrl_alt_bksp
|
||||||
es-dvorak es microsoftpro dvorak 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
|
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
../TEST-01-BASIC/Makefile
|
|
||||||
@ -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 "$@"
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=TEST-60-MOUNT-RATELIMIT
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
|
|
||||||
@ -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
|
|
||||||
Loading…
x
Reference in New Issue
Block a user