Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

systemctl: switch-root: align behaviour with manual #3958

Closed
wants to merge 1 commit into from

Conversation

esmil
Copy link
Contributor

@esmil esmil commented Aug 14, 2016

The manual says no state will be passed from one systemd to the next if the path of the next init
is specified on the command line. However systemctl tries to detect if the next init
is systemd and then pass it's state anyway. Just delete this code.

The specific problem this solves for me is that sometimes systemd in my initrd will pass a state to systemd on my rootfs that says local-fs.target is up. However local-fs.target on my root filesystem has more dependencies than in the initrd, so some filesystems are not mounted before systemd-tmpfiles is run to create files on them.

This patch at least let me work around the problem by specifically telling the initrd to not pass any state to systemd in the rootfs.

The manual says no state will be passed from one
systemd to the next if the path of the next init
is specified on the command line.
However systemctl tries to detect if the next init
is systemd and then pass it's state anyway.
Just delete this code.
@arvidjaar
Copy link
Contributor

sometimes systemd in my initrd will pass a state to systemd on my rootfs that says local-fs.target is up

local-fs.target should be stopped before switching root. If this does not happen, you are probably seeing effect of #3436

@esmil
Copy link
Contributor Author

esmil commented Aug 14, 2016

Sorry, my bad. I turns out that one of the two custom units I added to the initrd indirectly created a dependency link between initrd-switch-root.target and local-fs.target, and hence isolating the initrd-switch-root.target in the initrd did not deactivate the local-fs.target properly.

I still think this patch makes sense though. It should be possible to start systemd in the rootfs without transferring state. The default initrd-switch-root.service does not specify the next init, so you'd have to manually override that to notice this change.

@keszybz
Copy link
Member

keszybz commented Aug 16, 2016

I don't know. Transferring state like this is quite useful as a debug mechanism. I don't we should remove this capability unless there's a concrete reason.

@esmil
Copy link
Contributor Author

esmil commented Aug 16, 2016

This doesn't remove the capability to transfer the state at all. You just need to not specify the path to the new init (which initrd-switch-root.service does not do by default).

However without this patch it is not possible to disable transferring state if the next init is also systemd.

@poettering
Copy link
Member

No, this really should stay. We should pass all matching state from the initrd to the main system. After all it's highly relevant whether for example an fsck on the root fs failed or not, and "systemctl status" should show that after the system is up.

Units in the initrd and on the host that have the same meaning should not really change meaning. It's OK if they change config slightly, but they really should semantically have the same meaning. If they change meaning they should really change name too. Specifically this means in your case local-fs.target should not be used in the initrd (unless you know for sure that no further file systems shall be mounted during runtime, before the services are up). There's initrd-fs.target specifically in order to have a different target for file systems mounted in the initrd.

I am pretty sure we should continue to pass as much state as we can, if we know that the destination init system is actually systemd.

I hope this makes sense, closing hence.

@esmil
Copy link
Contributor Author

esmil commented Aug 17, 2016

If you really want to make it impossible to start systemd in the rootfs without transferring state, then you really should at least document it.

It makes things very difficult to debug when the manual explicitly states that when you specify the path to the next init no state is passed, and then it does so anyway.

@poettering
Copy link
Member

I wouldn't call it "making it impossible"... I'd just call it "try hard to transfer the state if we can". But yeah, we should document this.

poettering added a commit to poettering/systemd that referenced this pull request Aug 19, 2016
…cross

As suggested:

systemd#3958 (comment)

Let's document that we try hard to pass system state from the initrd to the
host, and even compare the systemd binary paths.
@poettering
Copy link
Member

I posted #3995 which adds a quick note about this behaviour to the systemctl man page.

@esmil
Copy link
Contributor Author

esmil commented Aug 19, 2016

If it's not impossible then please tell me how to start systemd in the rootfs without transferring state as the code is now without some hack like renaming /usr/lib/systemd/systemd in the rootfs to /usr/lib/imspartacus.

In other words I totally agree that transferring state is a nice feature and should be used when possible. I just don't see why we can't (at least for debugging purposes) have a way to turn it off without resorting to silly name games.

@poettering
Copy link
Member

Well, I didn't say it's not impossible. I just said I wouldn't call it that way, and just focus on the good... I'd be open to maybe add a way how the passing of state can be forcibly disabled. For example, we could add permit that if the init path is prefixed with ! or so, we'd never pass state. Would that work for you?

@esmil
Copy link
Contributor Author

esmil commented Aug 19, 2016

Sure that would work. I just think it would be way easier to implement that "feature" by actually doing what the manual already says -- and that by just removing code.

@esmil
Copy link
Contributor Author

esmil commented Aug 19, 2016

I mean the code in question only does anything if the given path is the canonical path to the systemd binary or a link to it. But this is exactly the situation where you might as well not give a path if you want the state transferred. So I think the already documented behaviour makes a lot of sense.

@poettering
Copy link
Member

Well, the reason the code is like it is is because some real-life initrds specified the path explicitly and thus lost state... It's difficult to go back from that now.

@esmil
Copy link
Contributor Author

esmil commented Aug 19, 2016

..and when initrds start using ! will you then silently ignore that and pass state anyway?

I mean you already documented it so if people pass the path then they probably expected the documented behaviour. I think it'd be much better if the initrd generators were fixed rather than systemd trying to trick them. In most distros on which systemd will be updated the kernel and initrd generators will likely also be updated and initrds regenerated.

@poettering
Copy link
Member

well, the ! extension is an extension, it won't break existing code, as we previously explicitly forbid non-absolute path as second argument. However, changing behaviour of existing code is much more problematic, as initrd exists that specify the path and expect the state to be passed these days, and we cannot just stop passing it...

@poettering
Copy link
Member

Anyway, I'd be happy to take a patch that makes "!" as first char (or only char) in the init parameter to the method call a request to not pass state.

keszybz pushed a commit that referenced this pull request Aug 19, 2016
…cross (#3995)

As suggested:

#3958 (comment)

Let's document that we try hard to pass system state from the initrd to the
host, and even compare the systemd binary paths.
@keszybz
Copy link
Member

keszybz commented Aug 19, 2016

"!" sound quite cryptic. Why not have a new switch like '--no-state'?

@poettering
Copy link
Member

well, the question is how to pass that PID 1... there we currently have a single method call SwitchRoot(). We'd have to add SwitchRootNoState() or so, to implement such a switch. Doing that is certainly an alternative, and less cryptic...

That said, I am not too concerned if this is a bit cryptic, it appears to me that only folks who know what they do should use this... Moreover I think we should be cosnervative with adding ever more and more new switches to systemctl... If you ask me we probably already have too many.

Following the scheme we use in nspawn and friends: maybe we should implement this via an additional env var or so that we check. i.e. consider this a hidden but supported feature, and don't list it in --help, but honour it via an env var, and then add SwitchRootNoState() to implement it.

@keszybz
Copy link
Member

keszybz commented Aug 19, 2016

Dunno, I have to admit that I haven't had the need to switch-root systemd without passing state. The reason for this RFE was the local-fs.target issue, but that appears to be (on the path to) being fixed. So maybe let's just forget about this until a real use case comes along again.

@poettering
Copy link
Member

@keszybz yes, I fully agree. (but wanted to be nice to @esmil ;-))

@chaidisheng
Copy link

so finally how to solved this problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

None yet

5 participants