1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #12013 from yuwata/fix-switchroot-11997

core: on switching root do not emit device state change based on enumeration results
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-04-02 16:06:07 +02:00 committed by GitHub
commit 237ebf61e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 94 additions and 13 deletions

View File

@ -1492,7 +1492,7 @@ static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *e
}
static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
char *ri = NULL, *rt = NULL;
_cleanup_free_ char *ri = NULL, *rt = NULL;
const char *root, *init;
Manager *m = userdata;
struct statvfs svfs;
@ -1564,17 +1564,12 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
if (!isempty(init)) {
ri = strdup(init);
if (!ri) {
free(rt);
if (!ri)
return -ENOMEM;
}
}
free(m->switch_root);
m->switch_root = rt;
free(m->switch_root_init);
m->switch_root_init = ri;
free_and_replace(m->switch_root, rt);
free_and_replace(m->switch_root_init, ri);
m->objective = MANAGER_SWITCH_ROOT;

View File

@ -666,9 +666,13 @@ static void device_found_changed(Device *d, DeviceFound previous, DeviceFound no
}
static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
Manager *m;
assert(d);
if (MANAGER_IS_RUNNING(UNIT(d)->manager)) {
m = UNIT(d)->manager;
if (MANAGER_IS_RUNNING(m) && (m->honor_device_enumeration || MANAGER_IS_USER(m))) {
DeviceFound n, previous;
/* When we are already running, then apply the new mask right-away, and trigger state changes

View File

@ -1908,9 +1908,8 @@ static int invoke_main_loop(
*ret_shutdown_verb = NULL;
/* Steal the switch root parameters */
*ret_switch_root_dir = m->switch_root;
*ret_switch_root_init = m->switch_root_init;
m->switch_root = m->switch_root_init = NULL;
*ret_switch_root_dir = TAKE_PTR(m->switch_root);
*ret_switch_root_init = TAKE_PTR(m->switch_root_init);
return 0;

View File

@ -1619,6 +1619,8 @@ static void manager_ready(Manager *m) {
/* Let's finally catch up with any changes that took place while we were reloading/reexecing */
manager_catchup(m);
m->honor_device_enumeration = true;
}
static Manager* manager_reloading_start(Manager *m) {
@ -3149,6 +3151,9 @@ int manager_serialize(
(void) serialize_bool(f, "taint-logged", m->taint_logged);
(void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
/* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
(void) serialize_bool(f, "honor-device-enumeration", !switching_root);
t = show_status_to_string(m->show_status);
if (t)
(void) serialize_item(f, "show-status", t);
@ -3377,6 +3382,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
else
m->service_watchdogs = b;
} else if ((val = startswith(l, "honor-device-enumeration="))) {
int b;
b = parse_boolean(val);
if (b < 0)
log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val);
else
m->honor_device_enumeration = b;
} else if ((val = startswith(l, "show-status="))) {
ShowStatus s;
@ -3567,6 +3581,11 @@ int manager_reload(Manager *m) {
assert(m->n_reloading > 0);
m->n_reloading--;
/* On manager reloading, device tag data should exists, thus, we should honor the results of device
* enumeration. The flag should be always set correctly by the serialized data, but it may fail. So,
* let's always set the flag here for safety. */
m->honor_device_enumeration = true;
manager_ready(m);
m->send_reloading_done = true;

View File

@ -395,6 +395,8 @@ struct Manager {
* multiple times on the same unit. */
unsigned sigchldgen;
unsigned notifygen;
bool honor_device_enumeration;
};
#define MANAGER_IS_SYSTEM(m) ((m)->unit_file_scope == UNIT_FILE_SYSTEM)

View File

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

View File

@ -0,0 +1,49 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -e
TEST_DESCRIPTION="plugged -> dead -> plugged issue #11997"
TEST_NO_NSPAWN=1
. $TEST_BASE_DIR/test-functions
QEMU_TIMEOUT=300
test_setup() {
create_empty_image
mkdir -p $TESTDIR/root
mount ${LOOPDEV}p1 $TESTDIR/root
(
LOG_LEVEL=5
eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
setup_basic_environment
# mask some services that we do not want to run in these tests
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
# setup the testsuite service
cat >$initdir/etc/systemd/system/testsuite.service <<EOF
[Unit]
Description=Testsuite service
[Service]
ExecStart=/bin/bash -x /testsuite.sh
Type=oneshot
StandardOutput=tty
StandardError=tty
EOF
cp testsuite.sh $initdir/
setup_testsuite
) || return 1
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
}
do_test "$@"

View File

@ -0,0 +1,12 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
set -ex
set -o pipefail
if journalctl -b | grep -e '\.device: Changed plugged -> dead'; then
exit 1
fi
echo OK > /testok
exit 0